Ejemplo n.º 1
0
 def listResources(self, resType, fullPaths=True):
     if resType in self.getResourcesTypes():
         prefix = ''
         if fullPaths:
             prefix = self.directory
         return [
             os.path.join(prefix, resName)
             for resName in self.resourcesNames
             if ResourcesTypes.isExtensionOfType(resName[-4:], resType)
         ]
     else:
         return []
Ejemplo n.º 2
0
 def loadShader(self, name):
     '''
     Loads the shader specified by the given name.
     @param name: The name of the shader, by convention it will be used as the basename
     of the shader file to load.
     @return: A pandac.PandaModules.Shader instance or None if the file was not found or could not get loaded.
     '''
     exts = ResourcesTypes.getExtensions(PanoConstants.RES_TYPE_SHADERS)
     if len(exts) == 1:
         return self._loadInternal(PanoConstants.RES_TYPE_SHADERS,
                                   name + exts[0])
     else:
         return self._loadInternal(PanoConstants.RES_TYPE_SHADERS, name)
Ejemplo n.º 3
0
 def preloadResources(self, resType):
     '''
     Pre-loads all discovered resources of the given type.
     For example preloadResources(PanoConstants.RES_TYPE_MODELS) will pre-load all models in all resource
     locations.
     @param resType: A constant that identifies the type of resources to preload.
     '''
     if self.log.isEnabledFor(logging.DEBUG):
         self.log.debug('Preloading resource types %s' %
                        ResourcesTypes.typeToStr(resType))
     locations = self.resLocations.get(resType)
     if locations is not None:
         for loc in locations:
             self.preloadResourceLocation(loc.name, [resType], False)
Ejemplo n.º 4
0
    def _storePreloaded(self, res, filename, location):
        '''
        Stores a resource in the special storage allocated for preloaded
        resources.
        @param res: The loaded resource, a pano.resources.Resource instance.
        @param filename: The full path to the file that contains the resource.
        @param location: The name of the resource location containing the resource.
        '''
        if self.log.isEnabledFor(logging.DEBUG):
            self.log.debug('adding pre-loaded resource %s of type %s' %
                           (filename, ResourcesTypes.typeToStr(res.type)))

        perLocation = self.preloadStore.get(location)
        if perLocation is None:
            perLocation = {}
        perLocation[filename] = res
        self.preloadStore[location] = perLocation
Ejemplo n.º 5
0
class DirectoryResourcesLocation(AbstractResourceLocation):
    '''
    Offers services for finding loading files from directories.
    '''
    def __init__(self,
                 directory,
                 name,
                 description,
                 resTypes,
                 hotswap=True,
                 checkPeriod=10):
        AbstractResourceLocation.__init__(self, name, description, resTypes,
                                          hotswap, checkPeriod)

        self.log = logging.getLogger('pano.directoryResource')

        # the directory to look into for supported resource types
        self.directory = directory

        # a sorted list of all filenames of supported types that were found in self.directory
        self.resourcesNames = []

    def dispose(self):
        self.resourcesNames = None

    def indexResources(self):

        # get a listing of the directory and match filenames against
        # all supported resource types
        try:
            filenames = dircache.listdir(self.directory)
        except Exception, e:
            # dircache.listdir can throw
            self.log.exception('error while calling dircache.listdir')
            return

        suffixes = []
        for resType in self.resTypes:
            suffixes.extend(ResourcesTypes.getExtensions(resType))

        suffixes = tuple(suffixes)
        self.resourcesNames = [
            item for item in filenames if item.endswith(suffixes)
        ]
        self.resourcesNames.sort()
Ejemplo n.º 6
0
    def _loadParsedResource(self, resType, resName, filename, location):
        '''
        Handles loading of all parsed resources such as .pointer, .node, .item, etc. resources.
        Since parsed resources are all text based, we assume that they are encoded in UTF-8 in order
        to support multilingual elements.

        @param resType:  The type of the resource.
        @param resName:  The name to give to the newly constructed resource.
        @param filename: The full path to the file that contains the resource.
        @param location: The resource location found to contain this file, indicates that the resource 
        has been located. 
        '''
        assert resType is not None and resType != PanoConstants.RES_TYPE_ALL, 'invalid resource type in loadGeneric'

        fileContents = location.getResourceAsString(filename, True)
        resObj = ResourcesTypes.constructParsedResource(resType, resName)
        resource = self.parsers[resType].parse(resObj, fileContents)
        return resource
Ejemplo n.º 7
0
 def _listResourcesImpl(self, parent, resType, fullPaths = True):
     resFiles = []
     directories = []
     
     vfs = VirtualFileSystem.getGlobalPtr()
     filesList = vfs.scanDirectory(parent)
     if filesList is None:
         return directories
     
     for i in xrange(filesList.getNumFiles()):            
         fileEntry = filesList.getFile(i)            
         if fileEntry.isDirectory():
             directories.append(fileEntry.getFilename())
             continue
         
         if ResourcesTypes.isExtensionOfType(fileEntry.getFilename().getExtension(), resType):
             resFiles.append(fileEntry.getFilename().getFullpath() if fullPaths else fileEntry.getFilename().getBasename())
             
     for dir in directories:
         resFiles.extend(self._listResourcesImpl(dir, resType, fullPaths))
         
     return resFiles
Ejemplo n.º 8
0
    def _createButtons(self, cfg):
        '''
        Creates DirectGui elements for displaying the paging and scrolling buttons.
        The sprite names are read from the configuration.
        The create DirectButtons use sprites as images.
        @param cfg: a ConfigVars instance
        '''
        # button to display next page of items
        nxPgBtnSprite = cfg.get(PanoConstants.CVAR_INVENTORY_NEXTPAGE_SPRITE)
        nxPgBtnPressedSprite = cfg.get(
            PanoConstants.CVAR_INVENTORY_NEXTPAGE_PRESSED_SPRITE)
        nxPgBtnHoverSprite = cfg.get(
            PanoConstants.CVAR_INVENTORY_NEXTPAGE_HOVER_SPRITE)
        nxPgBtnPos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_NEXTPAGE_POS)

        # button to display previous page of items
        pvPgBtnSprite = cfg.get(PanoConstants.CVAR_INVENTORY_PREVPAGE_SPRITE)
        pvPgBtnPressedSprite = cfg.get(
            PanoConstants.CVAR_INVENTORY_PREVPAGE_PRESSED_SPRITE)
        pvPgBtnHoverSprite = cfg.get(
            PanoConstants.CVAR_INVENTORY_PREVPAGE_HOVER_SPRITE)
        pvPgBtnPos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_PREVPAGE_POS)

        # button to scroll to next items
        scrNxBtnSprite = cfg.get(
            PanoConstants.CVAR_INVENTORY_SCROLLNEXT_SPRITE)
        scrNxBtnPressedSprite = cfg.get(
            PanoConstants.CVAR_INVENTORY_SCROLLNEXT_PRESSED_SPRITE)
        scrNxBtnHoverSprite = cfg.get(
            PanoConstants.CVAR_INVENTORY_SCROLLNEXT_HOVER_SPRITE)
        scrNxBtnPos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_SCROLLNEXT_POS)

        # button to scroll to previous items
        scrPvBtnSprite = cfg.get(
            PanoConstants.CVAR_INVENTORY_SCROLLPREV_SPRITE)
        scrPvBtnPressedSprite = cfg.get(
            PanoConstants.CVAR_INVENTORY_SCROLLPREV_PRESSED_SPRITE)
        scrPvBtnHoverSprite = cfg.get(
            PanoConstants.CVAR_INVENTORY_SCROLLPREV_HOVER_SPRITE)
        scrPvBtnPos = cfg.getVec2(PanoConstants.CVAR_INVENTORY_SCROLLPREV_POS)

        sprites = self.game.getView().getSpritesFactory()
        origin = aspect2d.getRelativePoint(screen2d, VBase3(0, 0, 0))

        # for every button define property name, position, callback, list of sprites for normal, pressed and hover state
        pagingButtons = [
            ('nextPageButton', nxPgBtnPos, self._nextPageCallback,
             [(nxPgBtnSprite, 'next_page_sprite'),
              (nxPgBtnPressedSprite, 'next_page_pressed_sprite'),
              (nxPgBtnHoverSprite, 'next_page_hover_sprite')]),
            ('prevPageButton', pvPgBtnPos, self._previousPageCallback,
             [(pvPgBtnSprite, 'previous_page_sprite'),
              (pvPgBtnPressedSprite, 'previous_page_pressed_sprite'),
              (pvPgBtnHoverSprite, 'previous_page_hover_sprite')]),
            ('scrollNextButton', scrNxBtnPos, self._scrollNextCallback,
             [(scrNxBtnSprite, 'scroll_next_sprite'),
              (scrNxBtnPressedSprite, 'scroll_next_pressed_sprite'),
              (scrNxBtnHoverSprite, 'scroll_next_hover_sprite')]),
            ('scrollPrevButton', scrPvBtnPos, self._scrollPreviousCallback,
             [(scrPvBtnSprite, 'scroll_previous_sprite'),
              (scrPvBtnPressedSprite, 'scroll_previous_pressed_sprite'),
              (scrPvBtnHoverSprite, 'scroll_previous_hover_sprite')]),
        ]

        for buttonName, buttonPos, buttonCallback, spritesList in pagingButtons:
            buttonGeoms = [None, None, None, None]
            btnScrBounds = [0, 0, 0]
            i = 0
            for spriteFile, spriteName in spritesList:
                print 'adding sprite %s' % spriteName
                if spriteFile is not None:
                    spr = None
                    if spriteFile.rindex('.') >= 0:
                        ext = spriteFile[spriteFile.rindex('.'):]
                        print ext
                        if ResourcesTypes.isExtensionOfType(
                                ext, PanoConstants.RES_TYPE_IMAGES):
                            spr = Sprite(spriteName)
                            spr.image = spriteFile
                    else:
                        spr = self.game.getResources().loadSprite(spriteFile)

                    if spr:
                        buttonGeoms[i] = sprites.createSprite(spr).nodepath
                        buttonGeoms[i].setScale(1.0)
                        btnScrBounds = aspect2d.getRelativePoint(
                            screen2d, VBase3(spr.width, 1.0,
                                             spr.height)) - origin
                        btnScrBounds[2] *= -1

                i += 1

            if buttonGeoms[0] is not None:
                b = DirectButton(
                    geom=(buttonGeoms[0],
                          buttonGeoms[1] if buttonGeoms[1] else buttonGeoms[0],
                          buttonGeoms[2] if buttonGeoms[2] else buttonGeoms[0],
                          buttonGeoms[3]
                          if buttonGeoms[3] else buttonGeoms[0]),
                    relief=None)
                b['geom_pos'] = (0, 0, 0)
                b.setTransparency(1)

                # if position is omitted from the configuration, put the button on the upper left corner
                if buttonPos is not None:
                    b.setPos(
                        aspect2d.getRelativePoint(
                            screen2d, VBase3(buttonPos[0], 1.0, buttonPos[1])))
                else:
                    b.setPos(origin[0], 1.0, origin[2])

                b.setScale(btnScrBounds[0], 1.0, btnScrBounds[2])
                b.setFrameSize((0, btnScrBounds[0], 1.0, btnScrBounds[2]))
                b['command'] = buttonCallback
                b['extraArgs'] = (self.msn, )
                b.hide()
            else:
                b = None

            setattr(self, buttonName, b)
Ejemplo n.º 9
0
    def _loadInternal(self,
                      resType,
                      filename,
                      locationName=None,
                      preloading=False):
        '''
        Manages the actual loading of a resource given the resource filename and the resource location
        that contains it.

        @param resType: A constant that identifies the type of the resource.
        @param filename: The filename of the resource.
        @param locationName: The name of the resource location containing the resource. This is optional.
        @return: A pano.resources.Resource instance if preloading is True, or the actual resource instance
        if preloading is False or finally None if the resource couldn't be found.
        '''

        self.requests += 1

        if locationName is not None:
            location = self.locationsByName.get(locationName)
        else:
            location = self.locateResource(resType, filename)
        if location is None:
            self.log.error('Failed to locate resource %s' % filename)
            return None

        # get the full path to query the cache, sticky and preload stores
        fullPath = location.getResourceFullPath(filename)
        if fullPath is None:
            self.log.error('Failed to get full path to resource %s' % filename)
            return None

        # resource locations can be sticky
        if location.sticky:
            resource = self._getStickyResource(fullPath, resType)
            if resource is not None:
                if self.log.isEnabledFor(logging.DEBUG):
                    self.log.debug('Returning sticky resource %s' % fullPath)

                self.stickyLoads += 1
                if not preloading:
                    resource.requested = True
                return resource.data if not preloading else resource

        # if the location has a preload flag, then search first in the preload store
        if location.preload:
            resource = self._fetchPreloaded(fullPath, location.name)
            if resource is not None:
                self.preloadHits += 1
                if not preloading:
                    resource.requested = True
                return resource.data if not preloading else resource
            else:
                self.preloadMisses += 1

        # then search in our cache
#        resource = self._cacheLookup(fullPath, location.name)
#        if resource is not None:
#            if self.log.isEnabledFor(logging.DEBUG):
#                self.log.debug('Returning cached instance of resource %s' % fullPath)
#            if not preloading:
#                resource.requested = True
#            return resource.data if not preloading else resource

# finally load it from the resource location
        if ResourcesTypes.isParsedResource(resType):
            # Convention: construct resource name from the basename of the filename and by dropping the extension.
            resName = os.path.basename(filename)
            extIndex = resName.rfind('.')
            if extIndex >= 0:
                resName = resName[:extIndex]

            resData = self._loadParsedResource(resType, resName, fullPath,
                                               location)

        else:
            if ResourcesTypes.isPandaResource(resType):
                # for Panda resources we use the BaseLoader
                resName = filename
                try:
                    if resType == PanoConstants.RES_TYPE_MODELS:
                        resData = loader.loadModel(fullPath)

                    elif resType == PanoConstants.RES_TYPE_TEXTURES or resType == PanoConstants.RES_TYPE_VIDEOS:
                        resData = loader.loadTexture(fullPath)

                    elif resType == PanoConstants.RES_TYPE_IMAGES:
                        img = PNMImage()
                        img.read(fullPath)
                        resData = img

                    elif resType == PanoConstants.RES_TYPE_MUSIC:
                        resData = loader.loadMusic(fullPath)

                    elif resType == PanoConstants.RES_TYPE_SFX:
                        resData = loader.loadSfx(fullPath)

                    elif resType == PanoConstants.RES_TYPE_SHADERS:
                        resData = Shader.load(fullPath)

                except Exception:
                    self.log.exception(
                        'Panda loader failed to load resource %s' % fullPath)
                    return None

            elif ResourcesTypes.isStreamResource(resType):
                # we consider character based and binary based streams
                # by handling stream resources in a special way we can perhaps provide more efficient
                # handling of streams, i.e. memory mapped files, compressed streams, decryption, etc.
                resName = filename
                if resType == PanoConstants.RES_TYPE_SCRIPTS or resType == PanoConstants.RES_TYPE_TEXTS:
                    resData = self._loadCharacterStream(fullPath, location)
                else:
                    resData = self._loadBinaryStream(fullPath, location)

            elif ResourcesTypes.isOpaqueResource(resType):
                # opaque resources perform their own loading, we only load the file's contents without caring
                # about how it looks and pass it to the read() method.
                resName = os.path.basename(filename)
                resData = ResourcesTypes.constructOpaqueResource(
                    resType, resName, filename)
                opaque = self._loadBinaryStream(fullPath, location)
                fp = StringIO.StringIO(opaque)
                resData.read(fp)

            if resData is None:
                self.log.error('Failed to load resource %s' % fullPath)
                return None

        resource = Resource(resName, resData, resType, fullPath, location.name)
        resource.sticky = location.sticky
        resource.preload = location.preload
        if not preloading:
            resource.requested = True

        # consider caching the resource
        if not resource.sticky and not resource.preload:
            self._cacheResource(fullPath, resource, location.name)

        elif resource.sticky:
            self._addStickyResource(fullPath, resource, location.name)

        # when we are preloading, return the Resource instance instead
        return resource.data if not preloading else resource