def getWorldInfo(filename): worldAdapter = findAdapter(filename, readonly=True) try: displayNameLimit = 40 name = displayName(worldAdapter.filename) if len(name) > displayNameLimit: name = name[:displayNameLimit] + "..." if usefulFilename(worldAdapter) != displayName(worldAdapter.filename): name = "%s (%s)" % (name, usefulFilename(worldAdapter)) lastPlayed = lastPlayedTime(worldAdapter) lastPlayedText = lastPlayed.humanize() if lastPlayed else "Unknown" version = "Unknown Version" try: stackVersion = worldAdapter.blocktypes.itemStackVersion if stackVersion == VERSION_1_7: version = "Minecraft 1.7" if "FML" in worldAdapter.metadata.metadataTag: version = "MinecraftForge 1.7" if stackVersion == VERSION_1_8: version = "Minecraft 1.8" except Exception as e: log.warn("Failed to get version info for %s: %r", filename, e) return name, lastPlayedText, version except Exception as e: log.error("Failed getting world info for %s: %r", filename, e) return str(e), "", ""
def updateRecentFilesMenu(self): recentFiles = RecentFilesSetting.value() recentWorldsMenu = self.mainWindow.menuRecent_Worlds for i, child in enumerate(recentWorldsMenu.children()): if i < 2: continue # Skip "clear" and separator child.setParent(None) log.info("Updating recent files menu: (%d) %s", len(recentFiles), recentFiles) filenames = [] displayNames = collections.Counter() for filename in recentFiles: text = util.displayName(filename) filenames.append((text, filename)) displayNames[text] += 1 displayFilenames = [] for text, path in filenames: if displayNames[text] > 1: text += " (%s)" % path displayFilenames.append((text, path)) for text, path in displayFilenames: log.info("Adding %s", text) action = recentWorldsMenu.addAction(text) def _triggered(p): def _f(): self.loadFile(p) return _f triggered = _triggered(path) action.triggered.connect(triggered) action.__triggered = triggered
def __str__(self): if self.dimension: dimName = displayName(self.dimension.worldEditor.filename ) + ": " + self.dimension.dimName else: dimName = "None" return "%s(%r)" % (self.__class__.__name__, dimName)
def __init__(self, world, resourceLoader, blockModels, maxLOD=0, overrideMaxSize=None): """ Important members: textureData: RGBA Texture Data as a numpy array. texCoordsByName: Dictionary of texture coordinates. Usable for textures loaded using the extraTextures argument or from block definitions. Maps "texture_name" -> (left, top, right, bottom) :param world: :type world: mceditlib.worldeditor.WorldEditor :param resourceLoader: :type resourceLoader: mcedit2.resourceloader.ResourceLoader :param blockModels: :type blockModels: mcedit2.rendering.blockmodels.BlockModels :param maxLOD: Adds wrapped borders to each texture to allow mipmapping at this level of detail :type maxLOD: int :param overrideMaxSize: Override the maximum texture size - ONLY use for testing TextureAtlas without creating a GL context. :type overrideMaxSize: int or None :return: :rtype: TextureAtlas """ self.overrideMaxSize = overrideMaxSize self.blockModels = blockModels self.blocktypes = world.blocktypes self._filename = world.filename self._resourceLoader = resourceLoader self._lightTexture = None self._terrainTexture = None self._maxLOD = maxLOD names = set() self._rawTextures = rawTextures = [] assert "MCEDIT_UNKNOWN" in blockModels.getTextureNames() for filename in blockModels.getTextureNames(): if filename in names: continue try: f = self._openImageStream(filename) rawTextures.append((filename, ) + loadPNGData(f.read())) names.add(filename) log.debug("Loaded texture %s", filename) except ResourceNotFound as e: log.error("Could not load texture %s: %r", filename, e) except Exception as e: log.exception("%s while loading texture '%s', skipping...", e, filename) rawSize = sum(a.nbytes for (n, w, h, a) in rawTextures) log.info("Preloaded %d textures for world %s (%i kB)", len(self._rawTextures), util.displayName(self._filename), rawSize / 1024)
def getWorldInfo(filename): worldAdapter = findAdapter(filename, readonly=True) try: displayNameLimit = 40 name = displayName(worldAdapter.filename) if len(name) > displayNameLimit: name = name[:displayNameLimit] + "..." if usefulFilename(worldAdapter) != displayName(worldAdapter.filename): name = "%s (%s)" % (name, usefulFilename(worldAdapter)) lastPlayed = lastPlayedTime(worldAdapter) lastPlayedText = lastPlayed.humanize() if lastPlayed else "Unknown" return name, lastPlayedText except EnvironmentError as e: log.error("Failed getting world info for %s: %s", filename, e) return str(e), ""
def __str__(self): try: if self.dimension: dimName = displayName(self.dimension.worldEditor.filename) + ": " + self.dimension.dimName else: dimName = "None" except Exception as e: return "%s trying to get node name" % e return "%s(%r)" % (self.__class__.__name__, dimName)
def __init__(self, world, resourceLoader, blockModels, maxLOD=0, overrideMaxSize=None): """ Important members: textureData: RGBA Texture Data as a numpy array. texCoordsByName: Dictionary of texture coordinates. Usable for textures loaded using the extraTextures argument or from block definitions. Maps "texture_name" -> (left, top, right, bottom) :param world: :type world: mceditlib.worldeditor.WorldEditor :param resourceLoader: :type resourceLoader: mcedit2.resourceloader.ResourceLoader :param blockModels: :type blockModels: mcedit2.rendering.blockmodels.BlockModels :param maxLOD: Adds wrapped borders to each texture to allow mipmapping at this level of detail :type maxLOD: int :param overrideMaxSize: Override the maximum texture size - ONLY use for testing TextureAtlas without creating a GL context. :type overrideMaxSize: int or None :return: :rtype: TextureAtlas """ self.overrideMaxSize = overrideMaxSize self.blockModels = blockModels self.blocktypes = world.blocktypes self._filename = world.filename self._resourceLoader = resourceLoader self._lightTexture = None self._terrainTexture = None self._maxLOD = maxLOD names = set() self._rawTextures = rawTextures = [] assert "MCEDIT_UNKNOWN" in blockModels.getTextureNames() for filename in blockModels.getTextureNames(): if filename in names: continue try: f = self._openImageStream(filename) rawTextures.append((filename,) + loadPNGData(f.read())) names.add(filename) log.debug("Loaded texture %s", filename) except ResourceNotFound as e: log.error("Could not load texture %s: %r", filename, e) except Exception as e: log.exception("%s while loading texture '%s', skipping...", e, filename) rawSize = sum(a.nbytes for (n, w, h, a) in rawTextures) log.info("Preloaded %d textures for world %s (%i kB)", len(self._rawTextures), util.displayName(self._filename), rawSize/1024)
def updateRecentFilesMenu(self): recentFiles = RecentFilesSetting.value() for filename in recentFiles: text = util.displayName(filename) action = self.recentFilesMenu.addAction(text) def _triggered(): self.loadFile(filename) action.triggered.connect(_triggered) action.__triggered = _triggered
def __init__(self, worldAdapter, parent=None): QtGui.QPushButton.__init__(self, parent) self.filename = worldAdapter.filename self.setCheckable(True) self.setFlat(True) try: # mapLabel = QtGui.QLabel() # mapLabel.setFixedSize(72, 72) displayNameLimit = 50 name = displayName(worldAdapter.filename) if len(name) > displayNameLimit: name = name[:displayNameLimit] + "..." self.displayNameLabel = QtGui.QLabel(name) self.lastPlayed = lastPlayedTime(worldAdapter) lastPlayedText = self.lastPlayed.humanize( ) if self.lastPlayed else "Unknown" self.lastPlayedLabel = QtGui.QLabel(lastPlayedText) #self.sizeLabel = QtGui.QLabel(self.tr("Calculating area...")) # areaText = self.tr("%.02f million square meters") % (world.chunkCount * 0.25) # diskSize = 0 # if hasattr(worldAdapter, 'worldFolder'): # folder = worldAdapter.worldFolder # for rf in folder.findRegionFiles(): # diskSize += os.stat(rf).st_size # else: # diskSize = os.stat(worldAdapter.filename).st_size # # self.diskSizeLabel = QtGui.QLabel(self.tr("%0.2f MB") % (diskSize / 1000000.0)) infoColumn = Column( self.displayNameLabel, self.lastPlayedLabel, #self.diskSizeLabel, None) #layout = Row(mapLabel, (infoColumn, 1), None) layout = infoColumn #if usefulFilename(world) == world.displayName: # boxLabelText = world.displayName #else: # boxLabelText = self.tr("%s (%s)" % (world.displayName, usefulFilename(world))) self.setLayout(layout) self.setMinimumSize(layout.sizeHint()) self.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.MinimumExpanding) except EnvironmentError as e: setWidgetError(self, e)
def load(self): if self._terrainTexture is not None: return maxLOD = min(4, self._maxLOD) if self.overrideMaxSize is None: if maxLOD: minFilter = GL.GL_NEAREST_MIPMAP_LINEAR else: minFilter = None self._terrainTexture = glutils.Texture(name="TextureAtlas", image=self.textureData.ravel(), width=self.width, height=self.height, minFilter=minFilter, maxLOD=maxLOD) self._terrainTexture.load() else: self._terrainTexture = object() if self._lightTexture is None: self._lightTexture = LightTexture(self.dayTime, self.minBrightness) self._lightTexture.load() log.info("GL resources loaded for TextureAtlas for %s", util.displayName(self._filename))
def displayName(self): return displayName(self.filename)
def createAtlasImage(self): if self.textureData is not None: return if self.overrideMaxSize is None: maxSize = getGLMaximumTextureSize() else: maxSize = self.overrideMaxSize maxLOD = min(4, self._maxLOD) if maxLOD: borderSize = 1 << (maxLOD - 1) else: borderSize = 0 slots = [] atlasWidth = 0 atlasHeight = 0 self._rawTextures.sort(key=lambda (_, w, h, __): max(w, h), reverse=True) for path, w, h, data in self._rawTextures: w += borderSize * 2 h += borderSize * 2 for slot in slots: if slot.addTexture(path, w, h, data): log.debug("Slotting %s into an existing slot", path) break else: if atlasHeight < 24 * atlasWidth and atlasHeight + h < maxSize: # Prefer to lay out textures vertically, since animations are vertical strips slots.append(TextureSlot(0, atlasHeight, max(atlasWidth, w), atlasHeight + h)) atlasWidth = max(atlasWidth, w) atlasHeight = atlasHeight + h else: slots.append(TextureSlot(atlasWidth, 0, atlasWidth + w, max(atlasHeight, h))) atlasWidth = atlasWidth + w atlasHeight = max(atlasHeight, h) if atlasWidth > maxSize or atlasHeight > maxSize: raise ValueError("Building texture atlas: Textures too large for maximum texture size. (Needed " "%s, only got %s", (atlasWidth, atlasHeight), (maxSize, maxSize)) if not slots[-1].addTexture(path, w, h, data): raise ValueError("Building texture atlas: Internal error.") log.debug("Slotting %s into a newly created slot", path) self.width = atlasWidth self.height = atlasHeight self.textureData = texData = numpy.zeros((atlasHeight, atlasWidth, 4), dtype='uint8') self.textureData[:] = [0xff, 0x0, 0xff, 0xff] b = borderSize for slot in slots: for name, left, top, width, height, data in slot.textures: log.debug("Texture %s at (%d,%d,%d,%d)", name, left, top, width, height) texDataView = texData[top:top + height, left:left + width] if b: texDataView[b:-b, b:-b] = data # Wrap texture edges to avoid antialiasing bugs at edges of blocks texDataView[-b:, b:-b] = data[:b] texDataView[:b, b:-b] = data[-b:] texDataView[:, -b:] = texDataView[:, b:2 * b] texDataView[:, :b] = texDataView[:, -b * 2:-b] else: texDataView[:] = data self.texCoordsByName[name] = left + b, top + b, width - 2 * b, height - 2 * b totalSize = self.width * self.height * 4 usedSize = sum(sum(width * height for _, _, _, width, height, _ in slot.textures) for slot in slots) * 4 log.info("Terrain atlas created for world %s (%d/%d kB)", util.displayName(self._filename), usedSize / 1024, totalSize / 1024) self.blockModels.cookQuads(self)
def __str__(self): if self.dimension: dimName = displayName(self.dimension.worldEditor.filename) + ": " + self.dimension.dimName else: dimName = "None" return "%s(%r)" % (self.__class__.__name__, dimName)
def tabCaption(self): return util.displayName(self.filename)
def __str__(self): return "%s(%r)" % (self.__class__.__name__, displayName(self.dimension.worldEditor.filename))
def load(self): if self._terrainTexture: return if self.overrideMaxSize is None: maxSize = getGLMaximumTextureSize() else: maxSize = self.overrideMaxSize maxLOD = min(4, self._maxLOD) if not bool(GL.glGenerateMipmap): maxLOD = 0 if maxLOD: borderSize = 1 << (maxLOD - 1) else: borderSize = 0 slots = [] atlasWidth = 0 atlasHeight = 0 self._rawTextures.sort(key=lambda (_, w, h, __): max(w, h), reverse=True) for name, w, h, data in self._rawTextures: w += borderSize * 2 h += borderSize * 2 for slot in slots: if slot.addTexture(name, w, h, data): log.debug("Slotting %s into an existing slot", name) break else: if atlasHeight < 24 * atlasWidth and atlasHeight + h < maxSize: # Prefer to lay out textures vertically, since animations are vertical strips slots.append(TextureSlot(0, atlasHeight, max(atlasWidth, w), atlasHeight + h)) atlasWidth = max(atlasWidth, w) atlasHeight = atlasHeight + h else: slots.append(TextureSlot(atlasWidth, 0, atlasWidth + w, max(atlasHeight, h))) atlasWidth = atlasWidth + w atlasHeight = max(atlasHeight, h) if atlasWidth > maxSize or atlasHeight > maxSize: raise ValueError("Building texture atlas: Textures too large for maximum texture size. (Needed " "%s, only got %s", (atlasWidth, atlasHeight), (maxSize, maxSize)) if not slots[-1].addTexture(name, w, h, data): raise ValueError("Building texture atlas: Internal error.") log.debug("Slotting %s into a newly created slot", name) self.textureData = texData = numpy.zeros((atlasHeight, atlasWidth, 4), dtype='uint8') self.textureData[:] = [0xff, 0x0, 0xff, 0xff] self.texCoordsByName = {} b = borderSize for slot in slots: for name, left, top, width, height, data in slot.textures: log.debug("Texture %s at (%d,%d,%d,%d)", name, left, top, width, height) texDataView = texData[top:top + height, left:left + width] if b: texDataView[b:-b, b:-b] = data # Wrap texture edges to avoid antialiasing bugs at edges of blocks texDataView[-b:, b:-b] = data[:b] texDataView[:b, b:-b] = data[-b:] texDataView[:, -b:] = texDataView[:, b:2 * b] texDataView[:, :b] = texDataView[:, -b * 2:-b] else: texDataView[:] = data self.texCoordsByName[name] = left + b, top + b, width - 2 * b, height - 2 * b def _load(): GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, atlasWidth, atlasHeight, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, self.textureData.ravel()) if self.overrideMaxSize is None: if maxLOD: minFilter = GL.GL_NEAREST_MIPMAP_LINEAR else: minFilter = None self._terrainTexture = glutils.Texture(_load, minFilter=minFilter, maxLOD=maxLOD) self._terrainTexture.load() else: self._terrainTexture = object() self.width = atlasWidth self.height = atlasHeight totalSize = atlasWidth * atlasHeight * 4 usedSize = sum(sum(width * height for _, _, _, width, height, _ in slot.textures) for slot in slots) * 4 log.info("Terrain atlas created for world %s (%d/%d kB)", util.displayName(self._filename), usedSize / 1024, totalSize / 1024)
def load(self): if self._terrainTexture: return if self.overrideMaxSize is None: maxSize = getGLMaximumTextureSize() else: maxSize = self.overrideMaxSize maxLOD = min(4, self._maxLOD) if not bool(GL.glGenerateMipmap): maxLOD = 0 if maxLOD: borderSize = 1 << (maxLOD - 1) else: borderSize = 0 slots = [] atlasWidth = 0 atlasHeight = 0 self._rawTextures.sort(key=lambda (_, w, h, __): max(w, h), reverse=True) for name, w, h, data in self._rawTextures: w += borderSize * 2 h += borderSize * 2 for slot in slots: if slot.addTexture(name, w, h, data): log.debug("Slotting %s into an existing slot", name) break else: if atlasHeight < 24 * atlasWidth and atlasHeight + h < maxSize: # Prefer to lay out textures vertically, since animations are vertical strips slots.append( TextureSlot(0, atlasHeight, max(atlasWidth, w), atlasHeight + h)) atlasWidth = max(atlasWidth, w) atlasHeight = atlasHeight + h else: slots.append( TextureSlot(atlasWidth, 0, atlasWidth + w, max(atlasHeight, h))) atlasWidth = atlasWidth + w atlasHeight = max(atlasHeight, h) if atlasWidth > maxSize or atlasHeight > maxSize: raise ValueError( "Building texture atlas: Textures too large for maximum texture size. (Needed " "%s, only got %s", (atlasWidth, atlasHeight), (maxSize, maxSize)) if not slots[-1].addTexture(name, w, h, data): raise ValueError("Building texture atlas: Internal error.") log.debug("Slotting %s into a newly created slot", name) self.textureData = texData = numpy.zeros((atlasHeight, atlasWidth, 4), dtype='uint8') self.textureData[:] = [0xff, 0x0, 0xff, 0xff] self.texCoordsByName = {} b = borderSize for slot in slots: for name, left, top, width, height, data in slot.textures: log.debug("Texture %s at (%d,%d,%d,%d)", name, left, top, width, height) texDataView = texData[top:top + height, left:left + width] if b: texDataView[b:-b, b:-b] = data # Wrap texture edges to avoid antialiasing bugs at edges of blocks texDataView[-b:, b:-b] = data[:b] texDataView[:b, b:-b] = data[-b:] texDataView[:, -b:] = texDataView[:, b:2 * b] texDataView[:, :b] = texDataView[:, -b * 2:-b] else: texDataView[:] = data self.texCoordsByName[ name] = left + b, top + b, width - 2 * b, height - 2 * b def _load(): GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, atlasWidth, atlasHeight, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, self.textureData.ravel()) if self.overrideMaxSize is None: if maxLOD: minFilter = GL.GL_NEAREST_MIPMAP_LINEAR else: minFilter = None self._terrainTexture = glutils.Texture(_load, minFilter=minFilter, maxLOD=maxLOD) self._terrainTexture.load() else: self._terrainTexture = object() self.width = atlasWidth self.height = atlasHeight totalSize = atlasWidth * atlasHeight * 4 usedSize = sum( sum(width * height for _, _, _, width, height, _ in slot.textures) for slot in slots) * 4 log.info("Terrain atlas created for world %s (%d/%d kB)", util.displayName(self._filename), usedSize / 1024, totalSize / 1024)