mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-12 00:35:56 -04:00
display lists for screen gui and general performance improvement in monospace font renderer (not rendering spaces, just translate)
This commit is contained in:
parent
20028c99ed
commit
16ec4f6acd
@ -5,19 +5,29 @@ import net.minecraft.client.gui.Gui
|
||||
import org.lwjgl.opengl.GL11
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraft.client.renderer.Tessellator
|
||||
import net.minecraft.client.renderer.GLAllocation
|
||||
import net.minecraft.client.renderer.texture.TextureManager
|
||||
|
||||
/**
|
||||
* This GUI shows the buffer of a single screen.
|
||||
*
|
||||
* The window is sized to fit the contents of the buffer. If the buffer is
|
||||
* smaller than the overall available space, the window is centered. if it is
|
||||
* larger, the content is scaled down to fit the available space.
|
||||
*
|
||||
* Text and background are cached in display lists, so updateText() must be
|
||||
* called whenever the text actually changes, otherwise there will be no change
|
||||
* in the text displayed in the GUI.
|
||||
*/
|
||||
class GuiScreen(val tileEntity: TileEntityScreen) extends net.minecraft.client.gui.GuiScreen {
|
||||
tileEntity.gui = Some(this)
|
||||
|
||||
private val borders = new ResourceLocation("opencomputers", "textures/gui/borders.png")
|
||||
|
||||
private val margin = 7
|
||||
private val innerMargin = 1
|
||||
|
||||
var (x, y, innerWidth, innerHeight, scale) = (0, 0, 0, 0, 0.0)
|
||||
|
||||
/** Must be called when the size of the underlying screen changes */
|
||||
def setSize(w: Double, h: Double) = {
|
||||
val totalMargin = (margin + innerMargin) * 2
|
||||
// Re-compute sizes and positions.
|
||||
val totalMargin = (GuiScreen.margin + GuiScreen.innerMargin) * 2
|
||||
val bufferWidth = w * MonospaceFontRenderer.fontWidth
|
||||
val bufferHeight = h * MonospaceFontRenderer.fontHeight
|
||||
val bufferScaleX = ((width - totalMargin) / bufferWidth) min 1
|
||||
@ -27,11 +37,19 @@ class GuiScreen(val tileEntity: TileEntityScreen) extends net.minecraft.client.g
|
||||
innerHeight = (bufferHeight * scale + 1).ceil.toInt
|
||||
x = (width - (innerWidth + totalMargin)) / 2
|
||||
y = (height - (innerHeight + totalMargin)) / 2
|
||||
|
||||
// Re-build display lists.
|
||||
GuiScreen.compileBackground(innerWidth, innerHeight)
|
||||
GuiScreen.compileText(scale, tileEntity.component.lines)
|
||||
}
|
||||
|
||||
/** Must be called whenever the buffer of the underlying screen changes. */
|
||||
def updateText() = GuiScreen.compileText(scale, tileEntity.component.lines)
|
||||
|
||||
override def initGui() = {
|
||||
super.initGui()
|
||||
MonospaceFontRenderer.init(mc.renderEngine)
|
||||
GuiScreen.init(mc.renderEngine)
|
||||
val (w, h) = tileEntity.component.resolution
|
||||
setSize(w, h)
|
||||
}
|
||||
@ -45,57 +63,100 @@ class GuiScreen(val tileEntity: TileEntityScreen) extends net.minecraft.client.g
|
||||
GL11.glPushMatrix()
|
||||
GL11.glTranslatef(x, y, 0)
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F)
|
||||
setTexture(borders)
|
||||
|
||||
drawRectangle(
|
||||
0, 0, 7, 7,
|
||||
0, 0, 7, 7)
|
||||
drawRectangle(
|
||||
margin, 0, innerWidth, 7,
|
||||
7, 0, 8, 7)
|
||||
drawRectangle(
|
||||
margin + innerWidth, 0, 7, 7,
|
||||
8, 0, 15, 7)
|
||||
|
||||
drawRectangle(
|
||||
0, margin, 7, innerHeight,
|
||||
0, 7, 7, 8)
|
||||
drawRectangle(
|
||||
margin, margin, innerWidth, innerHeight,
|
||||
7, 7, 8, 8)
|
||||
drawRectangle(
|
||||
margin + innerWidth, margin, 7, innerHeight,
|
||||
8, 7, 15, 8)
|
||||
|
||||
drawRectangle(
|
||||
0, margin + innerHeight, 7, 7,
|
||||
0, 8, 7, 15)
|
||||
drawRectangle(
|
||||
margin, margin + innerHeight, innerWidth, 7,
|
||||
7, 8, 8, 15)
|
||||
drawRectangle(
|
||||
margin + innerWidth, margin + innerHeight, 7, 7,
|
||||
8, 8, 15, 15)
|
||||
|
||||
GL11.glTranslatef(margin + innerMargin, margin + innerMargin, 0)
|
||||
GL11.glScaled(scale, scale, 1)
|
||||
|
||||
tileEntity.component.lines.zipWithIndex.foreach {
|
||||
case (line, i) => MonospaceFontRenderer.drawString(line, 0, i * MonospaceFontRenderer.fontHeight)
|
||||
}
|
||||
GuiScreen.draw()
|
||||
GL11.glPopMatrix()
|
||||
|
||||
super.drawScreen(mouseX, mouseY, dt);
|
||||
}
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
}
|
||||
|
||||
private def setTexture(value: ResourceLocation) =
|
||||
mc.renderEngine.func_110577_a(value)
|
||||
/** We cache OpenGL stuff in a singleton to avoid having to re-allocate. */
|
||||
object GuiScreen {
|
||||
val margin = 7
|
||||
|
||||
private def drawRectangle(x: Double, y: Double, w: Double, h: Double, u1: Int, v1: Int, u2: Int, v2: Int) = {
|
||||
val t = Tessellator.instance
|
||||
val innerMargin = 1
|
||||
|
||||
private val borders = new ResourceLocation("opencomputers", "textures/gui/borders.png")
|
||||
|
||||
private var textureManager: Option[TextureManager] = None
|
||||
|
||||
private var displayLists: Option[Int] = None
|
||||
|
||||
private var buffer: Option[java.nio.IntBuffer] = None
|
||||
|
||||
def init(tm: TextureManager) = if (!textureManager.isDefined) {
|
||||
textureManager = Some(tm)
|
||||
displayLists = Some(GLAllocation.generateDisplayLists(2))
|
||||
buffer = Some(GLAllocation.createDirectIntBuffer(2))
|
||||
buffer.get.put(displayLists.get)
|
||||
buffer.get.put(displayLists.get + 1)
|
||||
}
|
||||
|
||||
def draw() = if (textureManager.isDefined) {
|
||||
buffer.get.rewind()
|
||||
GL11.glCallLists(buffer.get)
|
||||
}
|
||||
|
||||
private[gui] def compileBackground(innerWidth: Int, innerHeight: Int) =
|
||||
if (textureManager.isDefined) {
|
||||
GL11.glNewList(displayLists.get, GL11.GL_COMPILE)
|
||||
|
||||
setTexture(borders)
|
||||
|
||||
// Top border (left corner, middle bar, right corner).
|
||||
drawBorder(
|
||||
0, 0, 7, 7,
|
||||
0, 0, 7, 7)
|
||||
drawBorder(
|
||||
margin, 0, innerWidth, 7,
|
||||
7, 0, 8, 7)
|
||||
drawBorder(
|
||||
margin + innerWidth, 0, 7, 7,
|
||||
8, 0, 15, 7)
|
||||
|
||||
// Middle area (left bar, screen background, right bar).
|
||||
drawBorder(
|
||||
0, margin, 7, innerHeight,
|
||||
0, 7, 7, 8)
|
||||
drawBorder(
|
||||
margin, margin, innerWidth, innerHeight,
|
||||
7, 7, 8, 8)
|
||||
drawBorder(
|
||||
margin + innerWidth, margin, 7, innerHeight,
|
||||
8, 7, 15, 8)
|
||||
|
||||
// Bottom border (left corner, middle bar, right corner).
|
||||
drawBorder(
|
||||
0, margin + innerHeight, 7, 7,
|
||||
0, 8, 7, 15)
|
||||
drawBorder(
|
||||
margin, margin + innerHeight, innerWidth, 7,
|
||||
7, 8, 8, 15)
|
||||
drawBorder(
|
||||
margin + innerWidth, margin + innerHeight, 7, 7,
|
||||
8, 8, 15, 15)
|
||||
|
||||
GL11.glEndList()
|
||||
}
|
||||
|
||||
private[gui] def compileText(scale: Double, lines: Array[Array[Char]]) =
|
||||
if (textureManager.isDefined) {
|
||||
GL11.glNewList(displayLists.get + 1, GL11.GL_COMPILE)
|
||||
|
||||
GL11.glTranslatef(margin + innerMargin, margin + innerMargin, 0)
|
||||
GL11.glScaled(scale, scale, 1)
|
||||
lines.zipWithIndex.foreach {
|
||||
case (line, i) => MonospaceFontRenderer.drawString(line, 0, i * MonospaceFontRenderer.fontHeight)
|
||||
}
|
||||
|
||||
GL11.glEndList()
|
||||
}
|
||||
|
||||
private def drawBorder(x: Double, y: Double, w: Double, h: Double, u1: Int, v1: Int, u2: Int, v2: Int) = {
|
||||
val (u1d, u2d, v1d, v2d) = (u1 / 16.0, u2 / 16.0, v1 / 16.0, v2 / 16.0)
|
||||
val t = Tessellator.instance
|
||||
t.startDrawingQuads()
|
||||
t.addVertexWithUV(x, y + h, 0, u1d, v2d)
|
||||
t.addVertexWithUV(x + w, y + h, 0, u2d, v2d)
|
||||
@ -103,4 +164,7 @@ class GuiScreen(val tileEntity: TileEntityScreen) extends net.minecraft.client.g
|
||||
t.addVertexWithUV(x, y, 0, u1d, v1d)
|
||||
t.draw()
|
||||
}
|
||||
|
||||
private def setTexture(value: ResourceLocation) =
|
||||
textureManager.get.func_110577_a(value)
|
||||
}
|
@ -41,7 +41,12 @@ object MonospaceFontRenderer {
|
||||
val vOffset = vStep * 1 / 20
|
||||
val vSize = vStep * 18 / 20
|
||||
val t = Tessellator.instance
|
||||
for (index <- (32 until 0x7F).union(0x9F until 0xFF)) {
|
||||
// Special case for whitespace: just translate, don't render.
|
||||
GL11.glNewList(charLists + 32, GL11.GL_COMPILE)
|
||||
GL11.glTranslatef(charWidth, 0, 0)
|
||||
GL11.glEndList()
|
||||
// Now create lists for all printable chars.
|
||||
for (index <- (33 until 0x7F).union(0x9F until 0xFF)) {
|
||||
// The font texture does not contain the 0-1F range, nor the 0x7F to
|
||||
// 0x9F range (control chars as per Character.isISOControl).
|
||||
val textureIndex =
|
||||
|
@ -46,19 +46,28 @@ class TileEntityScreen extends TileEntityRotatable with IScreenEnvironment {
|
||||
}
|
||||
|
||||
def onScreenSet(col: Int, row: Int, s: String) =
|
||||
if (!worldObj.isRemote) {
|
||||
if (worldObj.isRemote) {
|
||||
gui.foreach(_.updateText())
|
||||
}
|
||||
else {
|
||||
markAsChanged()
|
||||
ServerPacketSender.sendScreenSet(this, col, row, s)
|
||||
}
|
||||
|
||||
def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) =
|
||||
if (!worldObj.isRemote) {
|
||||
if (worldObj.isRemote) {
|
||||
gui.foreach(_.updateText())
|
||||
}
|
||||
else {
|
||||
markAsChanged()
|
||||
ServerPacketSender.sendScreenFill(this, col, row, w, h, c)
|
||||
}
|
||||
|
||||
def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) =
|
||||
if (!worldObj.isRemote) {
|
||||
if (worldObj.isRemote) {
|
||||
gui.foreach(_.updateText())
|
||||
}
|
||||
else {
|
||||
markAsChanged()
|
||||
ServerPacketSender.sendScreenCopy(this, col, row, w, h, tx, ty)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user