def createResourceStruct(resources, formatAsTree=False, updateOnlyExistingSprites=False): skippatt = re.compile(r'\.(meta|py)$', re.I) result = {} if formatAsTree: result = ExtMap() # Filter unwanted files for res in resources: if skippatt.search(res.path): continue result[res.id] = res # Update simple images for combImg in (x for x in result.values() if isinstance(x, CombinedImage)): for embImg in combImg.embeds: if embImg.id in result: result[embImg.id].attachCombinedImage(combImg) elif not updateOnlyExistingSprites: embImg.attachCombinedImage(combImg) result[embImg.id] = embImg # Flatten out the resource representation for resid, res in result.items(): result[resid] = res.toResinfo() # ExtMap returns nested maps if formatAsTree: result = result.getData() return result
def createResourceStruct(resources, formatAsTree=False, updateOnlyExistingSprites=False): skippatt = re.compile(r'\.(meta|py)$', re.I) result = {} if formatAsTree: result = ExtMap() # Filter unwanted files for res in resources: if skippatt.search(res.path): continue result[res.id] = res # Update simple images for combImg in (x for x in result.values() if isinstance(x, CombinedImage)): for embImg in combImg.embeds: if embImg.id in result: result[embImg.id].attachCombinedImage(combImg) elif not updateOnlyExistingSprites: embImg.attachCombinedImage(combImg) result[embImg.id] = embImg # Flatten out the resource representation for resid, res in result.items(): result[resid] = res.toResinfo() # Unify font map aliases if isinstance(res, FontMap): for glyphname, code in res.mapping.iteritems(): fdsc = "@%s/%s" % (res.alias, glyphname) if not fdsc in result: try: result[fdsc] = [ result[resid][1], round(result[resid][2] / code[1]), code[0] ] except: pass del result[resid][4] # ExtMap returns nested maps if formatAsTree: result = result.getData() return result
def createResourceStruct(resources, formatAsTree=False, updateOnlyExistingSprites=False): skippatt = re.compile(r'\.(meta|py)$', re.I) result = {} if formatAsTree: result = ExtMap() # Filter unwanted files for res in resources: if skippatt.search(res.path): continue result[res.id] = res # Update simple images for combImg in (x for x in result.values() if isinstance(x, CombinedImage)): for embImg in combImg.embeds: if embImg.id in result: result[embImg.id].attachCombinedImage(combImg) elif not updateOnlyExistingSprites: embImg.attachCombinedImage(combImg) result[embImg.id] = embImg # Flatten out the resource representation for resid, res in result.items(): result[resid] = res.toResinfo() # Unify font map aliases if isinstance(res, FontMap): for glyphname, code in res.mapping.iteritems(): fdsc = "@%s/%s" % (res.alias, glyphname) if not fdsc in result: result[fdsc] = [result[resid][1], round(result[resid][2] / code[1]), code[0]] del result[resid][4] # ExtMap returns nested maps if formatAsTree: result = result.getData() return result
def generateResourceInfoCode(self, script, settings, libs, format=False): # some helper functions def extractAssetPart(libresuri, imguri): pre,libsfx,imgsfx = Path.getCommonPrefix(libresuri, imguri) # split libresuri from imguri if imgsfx[0] == os.sep: imgsfx = imgsfx[1:] # strip leading '/' return imgsfx # use the bare img suffix as its asset Id ## # finds the package that needs this resource <assetId> and adds it # (polymorphic in the 4th param, use either simpleResVal *or* combImgObj as kwarg) # TODO: this might be very expensive (lots of lookup's) def addResourceToPackages(script, classToResourceMap, assetId, simpleResVal=None, combImgObj=None): ## # match an asset id or a combined image object def assetRexMatchItem(assetRex, item): if combImgObj: # combined image = object(used:True/False, embeds: {id:ImgInfoFmt}, info:ImgInfoFmt) for embId in item.embeds: if assetRex.match(embId): return True return False else: # assetId return assetRex.match(item) # -------------------------------------------------------- if combImgObj: resvalue = combImgObj.info.flatten() checkval = combImgObj else: resvalue = simpleResVal checkval = assetId classesUsing = set(()) for clazz, assetSet in classToResourceMap.items(): for assetRex in assetSet: if assetRexMatchItem(assetRex, checkval): classesUsing.add(clazz) break for package in script.packages: if classesUsing.intersection(set(package.classes)): package.data.resources[assetId] = resvalue return ## # return the (potentially empty) list of embedded image id's of a # combined image that are in filteredResources def requiredEmbeds(combImg, filteredResourceIds): # combImg = {info: ImgInfoFmt, embeds: {id:ImgInfoFmt}} return (x for x in combImg.embeds if x in filteredResourceIds) ## # create the final form of the data to be returned by generateResourceInfoCode def serialize(filteredResources, combinedImages, resdata): for resId, resval in filteredResources.items(): # build up resdata if isinstance(resval, ImgInfoFmt): resvalue = resval.flatten() else: # handle other resources resvalue = resval resdata[resId] = resvalue return resdata ## # loop through resources, invoking addResourceToPackages def addResourcesToPackages(resdata, combinedImages, classToResourceMap): for resId, resvalue in resdata.items(): # register the resource with the package needing it addResourceToPackages(script, classToResourceMap, resId, simpleResVal=resvalue) # for combined images, we have to check their embedded images against the packages for combId, combImg in combinedImages.items(): if combId in resdata: addResourceToPackages(script, classToResourceMap, combId, combImgObj=combImg) # handle tree structure of resource info if resources_tree: resdata = resdata._data return resdata ## # get the resource Id and resource value def analyseResource(resource, lib): ## # compute the resource value of an image for the script def imgResVal(resource): imgId = resource # Cache or generate if (imgId in imgLookupTable and imgLookupTable[imgId ]["time"] > os.stat(imgId ).st_mtime): imageInfo = imgLookupTable[imgId ]["content"] else: imageInfo = self._imageInfo.getImageInfo(imgId , assetId) imgLookupTable[imgId ] = {"time": time.time(), "content": imageInfo} # Now process the image information # use an ImgInfoFmt object, to abstract from flat format imgfmt = ImgInfoFmt() imgfmt.lib = lib['namespace'] if not 'type' in imageInfo: raise RuntimeError, "Unable to get image info from file: %s" % imgId imgfmt.type = imageInfo['type'] # Add this image # imageInfo = {width, height, filetype} if not 'width' in imageInfo or not 'height' in imageInfo: raise RuntimeError, "Unable to get image info from file: %s" % imgId imgfmt.width = imageInfo['width'] imgfmt.height = imageInfo['height'] imgfmt.type = imageInfo['type'] return imgfmt # ---------------------------------------------------------- imgpatt = re.compile(r'\.(png|jpeg|jpg|gif)$', re.I) librespath = os.path.normpath(os.path.join(lib['path'], lib['resource'])) assetId = extractAssetPart(librespath, resource) assetId = Path.posifyPath(assetId) if imgpatt.search(resource): # handle images resvalue = imgResVal(resource) else: # handle other resources resvalue = lib['namespace'] return assetId, resvalue ## # collect resources from the libs and put them in suitable data structures def registerResources(libs, filteredResources, combinedImages): skippatt = re.compile(r'\.(meta|py)$', re.I) for lib in libs: resourceList = self._resourceHandler.findAllResources([lib], None) # resourceList = [file1,file2,...] for resource in resourceList: if skippatt.search(resource): continue if assetFilter(resource): # add those anyway resId, resVal = analyseResource(resource, lib) filteredResources[resId] = resVal if self._resourceHandler.isCombinedImage(resource): # register those for later evaluation combId, combImgFmt = analyseResource(resource, lib) combObj = CombinedImage(resource) # this parses also the .meta file combObj.info = combImgFmt combinedImages[combId] = combObj return filteredResources, combinedImages ## # apply combined image info to the simple images, improving and extending # filteredResources def incorporateCombinedImages(filteredResources, combinedImages): for combId, combImg in combinedImages.items(): # combImg.embeds = {resId : ImgFmt} filteredResourceIds = filteredResources.keys() for embId in requiredEmbeds(combImg, filteredResourceIds): # patch simle image info lib = filteredResources[embId].lib # keep lib info filteredResources[embId] = combImg.embeds[embId] # replace info with combined info filteredResources[embId].lib = lib # restore original lib # add combined image if combId not in filteredResourceIds: filteredResources[combId] = combImg.info return filteredResources # -- main -------------------------------------------------------------- self._console.info("Analyzing assets...") self._console.indent() compConf = self._job.get("compile-options") compConf = ExtMap(compConf) resources_tree = compConf.get("code/resources-tree", False) resdata = {} if resources_tree: resdata = ExtMap() self._imageInfo = ImageInfo(self._console, self._cache) assetFilter, classToResourceMap= self._resourceHandler.getResourceFilterByAssets(self._classList) # read img cache file cacheId = "imginfo-%s" % self._config._fname imgLookupTable = cache.read(cacheId, None) if imgLookupTable == None: imgLookupTable = {} filteredResources = {} # type {resId : ImgInfoFmt|string} combinedImages = {} # type {imgId : CombinedImage} # 1st pass gathering relevant images and other resources from the libraries filteredResources, combinedImages = registerResources(libs, filteredResources, combinedImages) # 2nd pass patching simple image infos with combined info filteredResources = incorporateCombinedImages(filteredResources, combinedImages) # 3rd pass consume the info from filteredResources in various ways resdata = serialize(filteredResources, combinedImages, resdata) addResourcesToPackages(resdata, combinedImages, classToResourceMap) if resources_tree: resdata = resdata.getData() # write img cache file cache.write(cacheId, imgLookupTable) self._console.outdent() return resdata