mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-12 16:57:32 -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 org.lwjgl.opengl.GL11
|
||||||
import net.minecraft.util.ResourceLocation
|
import net.minecraft.util.ResourceLocation
|
||||||
import net.minecraft.client.renderer.Tessellator
|
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 {
|
class GuiScreen(val tileEntity: TileEntityScreen) extends net.minecraft.client.gui.GuiScreen {
|
||||||
tileEntity.gui = Some(this)
|
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)
|
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) = {
|
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 bufferWidth = w * MonospaceFontRenderer.fontWidth
|
||||||
val bufferHeight = h * MonospaceFontRenderer.fontHeight
|
val bufferHeight = h * MonospaceFontRenderer.fontHeight
|
||||||
val bufferScaleX = ((width - totalMargin) / bufferWidth) min 1
|
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
|
innerHeight = (bufferHeight * scale + 1).ceil.toInt
|
||||||
x = (width - (innerWidth + totalMargin)) / 2
|
x = (width - (innerWidth + totalMargin)) / 2
|
||||||
y = (height - (innerHeight + 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() = {
|
override def initGui() = {
|
||||||
super.initGui()
|
super.initGui()
|
||||||
MonospaceFontRenderer.init(mc.renderEngine)
|
MonospaceFontRenderer.init(mc.renderEngine)
|
||||||
|
GuiScreen.init(mc.renderEngine)
|
||||||
val (w, h) = tileEntity.component.resolution
|
val (w, h) = tileEntity.component.resolution
|
||||||
setSize(w, h)
|
setSize(w, h)
|
||||||
}
|
}
|
||||||
@ -45,57 +63,100 @@ class GuiScreen(val tileEntity: TileEntityScreen) extends net.minecraft.client.g
|
|||||||
GL11.glPushMatrix()
|
GL11.glPushMatrix()
|
||||||
GL11.glTranslatef(x, y, 0)
|
GL11.glTranslatef(x, y, 0)
|
||||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F)
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F)
|
||||||
setTexture(borders)
|
GuiScreen.draw()
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
GL11.glPopMatrix()
|
GL11.glPopMatrix()
|
||||||
|
|
||||||
super.drawScreen(mouseX, mouseY, dt);
|
super.drawScreen(mouseX, mouseY, dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
override def doesGuiPauseGame = false
|
override def doesGuiPauseGame = false
|
||||||
|
}
|
||||||
|
|
||||||
private def setTexture(value: ResourceLocation) =
|
/** We cache OpenGL stuff in a singleton to avoid having to re-allocate. */
|
||||||
mc.renderEngine.func_110577_a(value)
|
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 innerMargin = 1
|
||||||
val t = Tessellator.instance
|
|
||||||
|
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 (u1d, u2d, v1d, v2d) = (u1 / 16.0, u2 / 16.0, v1 / 16.0, v2 / 16.0)
|
||||||
|
val t = Tessellator.instance
|
||||||
t.startDrawingQuads()
|
t.startDrawingQuads()
|
||||||
t.addVertexWithUV(x, y + h, 0, u1d, v2d)
|
t.addVertexWithUV(x, y + h, 0, u1d, v2d)
|
||||||
t.addVertexWithUV(x + w, y + h, 0, u2d, 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.addVertexWithUV(x, y, 0, u1d, v1d)
|
||||||
t.draw()
|
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 vOffset = vStep * 1 / 20
|
||||||
val vSize = vStep * 18 / 20
|
val vSize = vStep * 18 / 20
|
||||||
val t = Tessellator.instance
|
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
|
// The font texture does not contain the 0-1F range, nor the 0x7F to
|
||||||
// 0x9F range (control chars as per Character.isISOControl).
|
// 0x9F range (control chars as per Character.isISOControl).
|
||||||
val textureIndex =
|
val textureIndex =
|
||||||
|
@ -46,19 +46,28 @@ class TileEntityScreen extends TileEntityRotatable with IScreenEnvironment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def onScreenSet(col: Int, row: Int, s: String) =
|
def onScreenSet(col: Int, row: Int, s: String) =
|
||||||
if (!worldObj.isRemote) {
|
if (worldObj.isRemote) {
|
||||||
|
gui.foreach(_.updateText())
|
||||||
|
}
|
||||||
|
else {
|
||||||
markAsChanged()
|
markAsChanged()
|
||||||
ServerPacketSender.sendScreenSet(this, col, row, s)
|
ServerPacketSender.sendScreenSet(this, col, row, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) =
|
def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) =
|
||||||
if (!worldObj.isRemote) {
|
if (worldObj.isRemote) {
|
||||||
|
gui.foreach(_.updateText())
|
||||||
|
}
|
||||||
|
else {
|
||||||
markAsChanged()
|
markAsChanged()
|
||||||
ServerPacketSender.sendScreenFill(this, col, row, w, h, c)
|
ServerPacketSender.sendScreenFill(this, col, row, w, h, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) =
|
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()
|
markAsChanged()
|
||||||
ServerPacketSender.sendScreenCopy(this, col, row, w, h, tx, ty)
|
ServerPacketSender.sendScreenCopy(this, col, row, w, h, tx, ty)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user