mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-16 10:51:55 -04:00
working on color screens
This commit is contained in:
parent
39b2c97010
commit
4ee76b146d
@ -1,91 +0,0 @@
|
||||
package li.cil.oc.client.gui
|
||||
|
||||
import li.cil.oc.Config
|
||||
import net.minecraft.client.renderer.GLAllocation
|
||||
import net.minecraft.client.renderer.Tessellator
|
||||
import net.minecraft.client.renderer.texture.TextureManager
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import org.lwjgl.opengl.GL11
|
||||
import scala.io.Source
|
||||
|
||||
object MonospaceFontRenderer {
|
||||
private val font = new ResourceLocation(Config.resourceDomain, "textures/font/chars.png")
|
||||
|
||||
private val chars = Source.fromInputStream(MonospaceFontRenderer.getClass.getResourceAsStream("/assets/" + Config.resourceDomain + "/textures/font/chars.txt")).mkString
|
||||
|
||||
private var instance: Option[Renderer] = None
|
||||
|
||||
def init(textureManager: TextureManager) =
|
||||
instance = instance.orElse(Some(new Renderer(textureManager)))
|
||||
|
||||
val (fontWidth, fontHeight) = (5, 9)
|
||||
|
||||
def drawString(value: Array[Char], x: Int, y: Int) = instance match {
|
||||
case None => // Do nothing, not initialized.
|
||||
case Some(renderer) => renderer.drawString(value, x, y)
|
||||
}
|
||||
|
||||
private class Renderer(private val textureManager: TextureManager) {
|
||||
/** Display lists, one per char (renders quad with char's uv coords). */
|
||||
private val charLists = GLAllocation.generateDisplayLists(256)
|
||||
|
||||
/** Buffer filled with char display lists to efficiently draw strings. */
|
||||
private val listBuffer = GLAllocation.createDirectIntBuffer(512)
|
||||
|
||||
// Set up the display lists.
|
||||
{
|
||||
val (charWidth, charHeight) = (MonospaceFontRenderer.fontWidth * 2, MonospaceFontRenderer.fontHeight * 2)
|
||||
val cols = 256 / charWidth
|
||||
val uStep = charWidth / 256.0
|
||||
val vStep = charHeight / 256.0
|
||||
val t = Tessellator.instance
|
||||
// Now create lists for all printable chars.
|
||||
for (index <- 1 until 0xFF) {
|
||||
val x = (index - 1) % cols
|
||||
val y = (index - 1) / cols
|
||||
val u = x * uStep
|
||||
val v = y * vStep
|
||||
GL11.glNewList(charLists + index, GL11.GL_COMPILE)
|
||||
t.startDrawingQuads()
|
||||
t.addVertexWithUV(0, charHeight, 0, u, v + vStep)
|
||||
t.addVertexWithUV(charWidth, charHeight, 0, u + uStep, v + vStep)
|
||||
t.addVertexWithUV(charWidth, 0, 0, u + uStep, v)
|
||||
t.addVertexWithUV(0, 0, 0, u, v)
|
||||
t.draw()
|
||||
GL11.glTranslatef(charWidth, 0, 0)
|
||||
GL11.glEndList()
|
||||
}
|
||||
// Special case for whitespace: just translate, don't render.
|
||||
GL11.glNewList(charLists + ' ', GL11.GL_COMPILE)
|
||||
GL11.glTranslatef(charWidth, 0, 0)
|
||||
GL11.glEndList()
|
||||
}
|
||||
|
||||
def drawString(value: Array[Char], x: Int, y: Int) = {
|
||||
setTexture(textureManager, MonospaceFontRenderer.font)
|
||||
GL11.glPushMatrix()
|
||||
GL11.glTranslatef(x, y, 0)
|
||||
GL11.glScalef(0.5f, 0.5f, 1)
|
||||
GL11.glColor4f(1, 1, 1, 1)
|
||||
for (c <- value) {
|
||||
val index = 1 + chars.indexOf(c) match {
|
||||
case -1 => chars.indexOf('?')
|
||||
case i => i
|
||||
}
|
||||
listBuffer.put(charLists + index)
|
||||
if (listBuffer.remaining == 0)
|
||||
flush()
|
||||
}
|
||||
flush()
|
||||
GL11.glPopMatrix()
|
||||
}
|
||||
|
||||
private def flush() = {
|
||||
listBuffer.flip()
|
||||
GL11.glCallLists(listBuffer)
|
||||
listBuffer.clear()
|
||||
}
|
||||
}
|
||||
|
||||
private def setTexture(tm: TextureManager, resource: ResourceLocation) = tm.bindTexture(resource)
|
||||
}
|
@ -2,6 +2,7 @@ package li.cil.oc.client.gui
|
||||
|
||||
import li.cil.oc.Config
|
||||
import li.cil.oc.client.PacketSender
|
||||
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
||||
import li.cil.oc.common.tileentity
|
||||
import net.minecraft.client.gui.{GuiScreen => MCGuiScreen}
|
||||
import net.minecraft.client.renderer.GLAllocation
|
||||
@ -11,6 +12,7 @@ import net.minecraft.util.ResourceLocation
|
||||
import org.lwjgl.input.Keyboard
|
||||
import org.lwjgl.opengl.GL11
|
||||
import scala.collection.mutable
|
||||
import li.cil.oc.util.PackedColor
|
||||
|
||||
/**
|
||||
* This GUI shows the buffer of a single screen.
|
||||
@ -47,11 +49,11 @@ class Screen(tileEntity: tileentity.Screen) extends MCGuiScreen {
|
||||
|
||||
// Re-build display lists.
|
||||
Screen.compileBackground(innerWidth, innerHeight)
|
||||
Screen.compileText(scale, screen.instance.lines)
|
||||
Screen.compileText(scale, screen.instance.lines, screen.instance.colors, screen.instance.depth)
|
||||
}
|
||||
|
||||
/** Must be called whenever the buffer of the underlying screen changes. */
|
||||
def updateText() = Screen.compileText(scale, screen.instance.lines)
|
||||
def updateText() = Screen.compileText(scale, screen.instance.lines, screen.instance.colors, screen.instance.depth)
|
||||
|
||||
override def handleKeyboardInput() {
|
||||
super.handleKeyboardInput()
|
||||
@ -182,14 +184,14 @@ object Screen {
|
||||
GL11.glEndList()
|
||||
}
|
||||
|
||||
private[gui] def compileText(scale: Double, lines: Array[Array[Char]]) =
|
||||
private[gui] def compileText(scale: Double, lines: Array[Array[Char]], colors:Array[Array[Int]], depth: PackedColor.Depth.Value) =
|
||||
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)
|
||||
lines.zip(colors).zipWithIndex.foreach {
|
||||
case ((line, color), i) => MonospaceFontRenderer.drawString(0, i * MonospaceFontRenderer.fontHeight, line, color, depth)
|
||||
}
|
||||
|
||||
GL11.glEndList()
|
||||
|
137
li/cil/oc/client/renderer/MonospaceFontRenderer.scala
Normal file
137
li/cil/oc/client/renderer/MonospaceFontRenderer.scala
Normal file
@ -0,0 +1,137 @@
|
||||
package li.cil.oc.client.renderer
|
||||
|
||||
import li.cil.oc.util.{RenderState, PackedColor}
|
||||
import li.cil.oc.{OpenComputers, Config}
|
||||
import net.minecraft.client.renderer.GLAllocation
|
||||
import net.minecraft.client.renderer.Tessellator
|
||||
import net.minecraft.client.renderer.texture.TextureManager
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import org.lwjgl.opengl.GL11
|
||||
import scala.io.Source
|
||||
|
||||
object MonospaceFontRenderer {
|
||||
private val font = new ResourceLocation(Config.resourceDomain, "textures/font/chars.png")
|
||||
|
||||
private val chars = Source.fromInputStream(MonospaceFontRenderer.getClass.getResourceAsStream("/assets/" + Config.resourceDomain + "/textures/font/chars.txt")).mkString
|
||||
|
||||
private var instance: Option[Renderer] = None
|
||||
|
||||
def init(textureManager: TextureManager) = this.synchronized(
|
||||
instance = instance.orElse(Some(new Renderer(textureManager))))
|
||||
|
||||
val (fontWidth, fontHeight) = (5, 9)
|
||||
|
||||
def drawString(x: Int, y: Int, value: Array[Char], color: Array[Int], depth: PackedColor.Depth.Value) = instance match {
|
||||
case None => OpenComputers.log.warning("Trying to render string with uninitialized MonospaceFontRenderer.")
|
||||
case Some(renderer) => renderer.drawString(x, y, value, color, depth)
|
||||
}
|
||||
|
||||
private class Renderer(private val textureManager: TextureManager) {
|
||||
/** Display lists, one per char (renders quad with char's uv coords). */
|
||||
private val charLists = GLAllocation.generateDisplayLists(256)
|
||||
|
||||
/** Buffer filled with char display lists to efficiently draw strings. */
|
||||
private val listBuffer = GLAllocation.createDirectIntBuffer(512)
|
||||
|
||||
private val (charWidth, charHeight) = (MonospaceFontRenderer.fontWidth * 2, MonospaceFontRenderer.fontHeight * 2)
|
||||
private val cols = 256 / charWidth
|
||||
private val uStep = charWidth / 256.0
|
||||
private val vStep = charHeight / 256.0
|
||||
|
||||
// Set up the display lists.
|
||||
{
|
||||
val t = Tessellator.instance
|
||||
// Now create lists for all printable chars.
|
||||
for (index <- 1 until 0xFF) {
|
||||
val x = (index - 1) % cols
|
||||
val y = (index - 1) / cols
|
||||
val u = x * uStep
|
||||
val v = y * vStep
|
||||
GL11.glNewList(charLists + index, GL11.GL_COMPILE)
|
||||
t.startDrawingQuads()
|
||||
t.addVertexWithUV(0, charHeight, 0, u, v + vStep)
|
||||
t.addVertexWithUV(charWidth, charHeight, 0, u + uStep, v + vStep)
|
||||
t.addVertexWithUV(charWidth, 0, 0, u + uStep, v)
|
||||
t.addVertexWithUV(0, 0, 0, u, v)
|
||||
t.draw()
|
||||
GL11.glTranslatef(charWidth, 0, 0)
|
||||
GL11.glEndList()
|
||||
}
|
||||
// Special case for whitespace: just translate, don't render.
|
||||
GL11.glNewList(charLists + ' ', GL11.GL_COMPILE)
|
||||
GL11.glTranslatef(charWidth, 0, 0)
|
||||
GL11.glEndList()
|
||||
}
|
||||
|
||||
def drawString(x: Int, y: Int, value: Array[Char], color: Array[Int], depth: PackedColor.Depth.Value) = {
|
||||
if (color.length != value.length) throw new IllegalArgumentException("Color count must match char count.")
|
||||
|
||||
textureManager.bindTexture(MonospaceFontRenderer.font)
|
||||
GL11.glPushMatrix()
|
||||
GL11.glPushAttrib(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT)
|
||||
GL11.glTranslatef(x, y, 0)
|
||||
GL11.glScalef(0.5f, 0.5f, 1)
|
||||
GL11.glDepthMask(false)
|
||||
RenderState.makeItBlend()
|
||||
|
||||
// Background first. We try to merge adjacent backgrounds of the same
|
||||
// color to reduce the number of quads we have to draw.
|
||||
var cbg = 0x000000
|
||||
var width = 0
|
||||
for (col <- color.map(PackedColor.unpackBackground(_, depth))) {
|
||||
if (col != cbg) {
|
||||
draw(cbg, width)
|
||||
cbg = col
|
||||
width = 0
|
||||
}
|
||||
width = width + 1
|
||||
}
|
||||
draw(cbg, width)
|
||||
|
||||
// Foreground second. We only have to flush when the color changes, so
|
||||
// unless every char has a different color this should be quite efficient.
|
||||
var cfg = 0x000000
|
||||
GL11.glColor3f(0, 0, 0)
|
||||
for ((ch, col) <- value.zip(color.map(PackedColor.unpackForeground(_, depth)))) {
|
||||
val index = 1 + chars.indexOf(ch) match {
|
||||
case -1 => chars.indexOf('?')
|
||||
case i => i
|
||||
}
|
||||
if (col != cfg) {
|
||||
// Color changed, force flush and adjust colors.
|
||||
flush()
|
||||
cfg = col
|
||||
GL11.glColor3ub(
|
||||
(cfg & 0xFF0000 >> 16).toByte,
|
||||
(cfg & 0x00FF00 >> 8).toByte,
|
||||
(cfg & 0x0000FF).toByte)
|
||||
}
|
||||
listBuffer.put(charLists + index)
|
||||
if (listBuffer.remaining == 0)
|
||||
flush()
|
||||
}
|
||||
flush()
|
||||
|
||||
GL11.glPopAttrib()
|
||||
GL11.glPopMatrix()
|
||||
}
|
||||
|
||||
private def draw(color: Int, width: Int) = if (color != 0 && width > 0) {
|
||||
val t = Tessellator.instance
|
||||
t.startDrawingQuads()
|
||||
t.setColorOpaque_I(color)
|
||||
t.addVertexWithUV(0, charHeight, 0, 0, vStep)
|
||||
t.addVertexWithUV(charWidth, charHeight, 0, width * uStep, vStep)
|
||||
t.addVertexWithUV(charWidth, 0, 0, width * uStep, 0)
|
||||
t.addVertexWithUV(0, 0, 0, 0, 0)
|
||||
t.draw()
|
||||
}
|
||||
|
||||
private def flush() = {
|
||||
listBuffer.flip()
|
||||
GL11.glCallLists(listBuffer)
|
||||
listBuffer.clear()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -5,7 +5,7 @@ import cpw.mods.fml.common.{TickType, ITickHandler}
|
||||
import java.util
|
||||
import java.util.concurrent.{TimeUnit, Callable}
|
||||
import li.cil.oc.Config
|
||||
import li.cil.oc.client.gui.MonospaceFontRenderer
|
||||
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
||||
import li.cil.oc.common.tileentity.Screen
|
||||
import li.cil.oc.util.RenderState
|
||||
import net.minecraft.client.Minecraft
|
||||
@ -130,8 +130,8 @@ object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with
|
||||
// Slightly offset the text so it doesn't clip into the screen.
|
||||
GL11.glTranslatef(0, 0, 0.01f)
|
||||
|
||||
for ((line, i) <- screen.instance.lines.zipWithIndex) {
|
||||
MonospaceFontRenderer.drawString(line, 0, i * MonospaceFontRenderer.fontHeight)
|
||||
for (((line, color), i) <- screen.instance.lines.zip(screen.instance.colors).zipWithIndex) {
|
||||
MonospaceFontRenderer.drawString(0, i * MonospaceFontRenderer.fontHeight, line, color, screen.instance.depth)
|
||||
}
|
||||
|
||||
GL11.glEndList()
|
||||
|
@ -3,12 +3,12 @@ package li.cil.oc.common.component
|
||||
import li.cil.oc.api.Persistable
|
||||
import li.cil.oc.api.network.Visibility
|
||||
import li.cil.oc.common.{tileentity, component}
|
||||
import li.cil.oc.util.TextBuffer
|
||||
import li.cil.oc.util.{PackedColor, TextBuffer}
|
||||
import li.cil.oc.{Config, util, api}
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
class Screen(val owner: Screen.Environment, val maxResolution: (Int, Int)) extends Persistable {
|
||||
private val buffer = new TextBuffer(maxResolution)
|
||||
private val buffer = new TextBuffer(maxResolution, PackedColor.Depth.OneBit)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@ -16,6 +16,10 @@ class Screen(val owner: Screen.Environment, val maxResolution: (Int, Int)) exten
|
||||
|
||||
def lines = buffer.buffer
|
||||
|
||||
def colors = buffer.color
|
||||
|
||||
def depth = buffer.depth
|
||||
|
||||
def resolution = buffer.size
|
||||
|
||||
def resolution_=(value: (Int, Int)) = {
|
||||
|
100
li/cil/oc/util/PackedColor.scala
Normal file
100
li/cil/oc/util/PackedColor.scala
Normal file
@ -0,0 +1,100 @@
|
||||
package li.cil.oc.util
|
||||
|
||||
object PackedColor {
|
||||
|
||||
object Depth extends Enumeration {
|
||||
val OneBit, EightBit, SixteenBit = Value
|
||||
}
|
||||
|
||||
private val rMask32 = 0xFF0000
|
||||
private val gMask32 = 0x00FF00
|
||||
private val bMask32 = 0x0000FF
|
||||
private val rShift32 = 16
|
||||
private val gShift32 = 8
|
||||
private val bShift32 = 0
|
||||
|
||||
// 7 6 5 4 3 2 1 0
|
||||
// r r r g g g b b : 3.3.2
|
||||
private val rMask8 = Integer.parseInt("11100000", 2)
|
||||
private val gMask8 = Integer.parseInt("00011100", 2)
|
||||
private val bMask8 = Integer.parseInt("00000011", 2)
|
||||
private val rShift8 = 5
|
||||
private val gShift8 = 2
|
||||
private val bShift8 = 0
|
||||
private val rScale8 = 255.0 / 0x7
|
||||
private val gScale8 = 255.0 / 0x7
|
||||
private val bScale8 = 255.0 / 0x3
|
||||
|
||||
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
// r r r r r g g g g g g b b b b b : 5.6.5
|
||||
private val rMask16 = Integer.parseInt("1111100000000000", 2)
|
||||
private val gMask16 = Integer.parseInt("0000011111100000", 2)
|
||||
private val bMask16 = Integer.parseInt("0000000000011111", 2)
|
||||
private val rShift16 = 11
|
||||
private val gShift16 = 5
|
||||
private val bShift16 = 0
|
||||
private val rScale16 = 255.0 / 0x1F
|
||||
private val gScale16 = 255.0 / 0x3F
|
||||
private val bScale16 = 255.0 / 0x1F
|
||||
|
||||
private def extractFrom1Bit(c: Short) = if (c == 0) 0x000000 else 0xFFFFFF
|
||||
|
||||
private def compressTo1Bit(c: Int) = (if (c == 0) 0 else 1).toShort
|
||||
|
||||
private def extractFrom8Bit(c: Short) = {
|
||||
val r = ((((c & rMask8) >>> rShift8) * rScale8).toInt << rShift32) & rMask32
|
||||
val g = ((((c & gMask8) >>> gShift8) * gScale8).toInt << gShift32) & gMask32
|
||||
val b = ((((c & bMask8) >>> bShift8) * bScale8).toInt << bShift32) & bMask32
|
||||
r | g | b
|
||||
}
|
||||
|
||||
private def compressTo8Bit(c: Int) = {
|
||||
val r = ((((c & rMask32) >>> rShift32) / rScale8).toInt << rShift8) & rMask8
|
||||
val g = ((((c & gMask32) >>> gShift32) / gScale8).toInt << gShift8) & gMask8
|
||||
val b = ((((c & bMask32) >>> bShift32) / bScale8).toInt << bShift8) & bMask8
|
||||
(r | g | b).toShort
|
||||
}
|
||||
|
||||
private def extractFrom16Bit(c: Short) = {
|
||||
val r = ((((c & rMask16) >>> rShift16) * rScale16).toInt << rShift32) & rMask32
|
||||
val g = ((((c & gMask16) >>> gShift16) * gScale16).toInt << gShift32) & gMask32
|
||||
val b = ((((c & bMask16) >>> bShift16) * bScale16).toInt << bShift32) & bMask32
|
||||
r | g | b
|
||||
}
|
||||
|
||||
private def compressTo16Bit(c: Int) = {
|
||||
val r = ((((c & rMask32) >>> rShift32) / rScale16).toInt << rShift16) & rMask16
|
||||
val g = ((((c & gMask32) >>> gShift32) / gScale16).toInt << gShift16) & gMask16
|
||||
val b = ((((c & bMask32) >>> bShift32) / bScale16).toInt << bShift16) & bMask16
|
||||
(r | g | b).toShort
|
||||
}
|
||||
|
||||
// Colors are packed: 0xFFFFBBBB (F = foreground, B = background)
|
||||
private val fgShift = 16
|
||||
private val bgShift = 0
|
||||
|
||||
def pack(foreground: Int, background: Int, depth: Depth.Value) =
|
||||
depth match {
|
||||
case Depth.OneBit => (compressTo1Bit(foreground) << fgShift) | (compressTo1Bit(background) << bgShift)
|
||||
case Depth.EightBit => (compressTo8Bit(foreground) << fgShift) | (compressTo8Bit(background) << bgShift)
|
||||
case Depth.SixteenBit => (compressTo16Bit(foreground) << fgShift) | (compressTo16Bit(background) << bgShift)
|
||||
}
|
||||
|
||||
def unpackForeground(color: Int, depth: Depth.Value) = {
|
||||
val c = (color >>> fgShift).toShort
|
||||
depth match {
|
||||
case Depth.OneBit => extractFrom1Bit(c)
|
||||
case Depth.EightBit => extractFrom8Bit(c)
|
||||
case Depth.SixteenBit => extractFrom16Bit(c)
|
||||
}
|
||||
}
|
||||
|
||||
def unpackBackground(color: Int, depth: Depth.Value) = {
|
||||
val c = (color >>> bgShift).toShort
|
||||
depth match {
|
||||
case Depth.OneBit => extractFrom1Bit(c)
|
||||
case Depth.EightBit => extractFrom8Bit(c)
|
||||
case Depth.SixteenBit => extractFrom16Bit(c)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
package li.cil.oc.util
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.nbt.NBTTagList
|
||||
import net.minecraft.nbt.NBTTagString
|
||||
import net.minecraft.nbt.{NBTTagIntArray, NBTTagCompound, NBTTagList, NBTTagString}
|
||||
|
||||
/**
|
||||
* This stores chars in a 2D-Array and provides some manipulation functions.
|
||||
@ -12,8 +10,30 @@ import net.minecraft.nbt.NBTTagString
|
||||
* relatively fast updates, given a smart algorithm (using copy()/fill()
|
||||
* instead of set()ing everything).
|
||||
*/
|
||||
class TextBuffer(var width: Int, var height: Int) {
|
||||
def this(size: (Int, Int)) = this(size._1, size._2)
|
||||
class TextBuffer(var width: Int, var height: Int, val depth: PackedColor.Depth.Value) {
|
||||
def this(size: (Int, Int), depth: PackedColor.Depth.Value) = this(size._1, size._2, depth)
|
||||
|
||||
private var foreground_ = 0xFFFFFF
|
||||
|
||||
private var background_ = 0x000000
|
||||
|
||||
private var packed = PackedColor.pack(foreground_, background_, depth)
|
||||
|
||||
def foreground = foreground_
|
||||
|
||||
def foreground_=(value: Int) = {
|
||||
foreground_ = value
|
||||
packed = PackedColor.pack(foreground_, background_, depth)
|
||||
}
|
||||
|
||||
def background = background_
|
||||
|
||||
def background_=(value: Int) = {
|
||||
background_ = value
|
||||
packed = PackedColor.pack(foreground_, background_, depth)
|
||||
}
|
||||
|
||||
var color = Array.fill(height, width)(packed)
|
||||
|
||||
var buffer = Array.fill(height, width)(' ')
|
||||
|
||||
@ -32,10 +52,13 @@ class TextBuffer(var width: Int, var height: Int) {
|
||||
val (w, h) = (iw max 1, ih max 1)
|
||||
if (width != w || height != h) {
|
||||
val newBuffer = Array.fill(h, w)(' ')
|
||||
(0 until (h min height)) foreach {
|
||||
y => Array.copy(buffer(y), 0, newBuffer(y), 0, w min width)
|
||||
}
|
||||
val newColor = Array.fill(h, w)(packed)
|
||||
(0 until (h min height)).foreach(y => {
|
||||
Array.copy(buffer(y), 0, newBuffer(y), 0, w min width)
|
||||
Array.copy(color(y), 0, newColor(y), 0, w min width)
|
||||
})
|
||||
buffer = newBuffer
|
||||
color = newColor
|
||||
width = w
|
||||
height = h
|
||||
true
|
||||
@ -52,10 +75,12 @@ class TextBuffer(var width: Int, var height: Int) {
|
||||
else {
|
||||
var changed = false
|
||||
val line = buffer(row)
|
||||
val lineColor = color(row)
|
||||
for (x <- col until ((col + s.length) min width)) if (x >= 0) {
|
||||
val c = s(x - col)
|
||||
changed = changed || (line(x) != c)
|
||||
changed = changed || (line(x) != c) || (lineColor(x) != packed)
|
||||
line(x) = c
|
||||
lineColor(x) = packed
|
||||
}
|
||||
changed
|
||||
}
|
||||
@ -68,9 +93,11 @@ class TextBuffer(var width: Int, var height: Int) {
|
||||
var changed = false
|
||||
for (y <- (row max 0) until ((row + h) min height)) {
|
||||
val line = buffer(y)
|
||||
val lineColor = color(y)
|
||||
for (x <- (col max 0) until ((col + w) min width)) {
|
||||
changed = changed || (line(x) != c)
|
||||
changed = changed || (line(x) != c) || (lineColor(x) != packed)
|
||||
line(x) = c
|
||||
lineColor(x) = packed
|
||||
}
|
||||
}
|
||||
changed
|
||||
@ -97,13 +124,16 @@ class TextBuffer(var width: Int, var height: Int) {
|
||||
var changed = false
|
||||
for (ny <- dy0 to dy1 by sy) {
|
||||
val nl = buffer(ny)
|
||||
val nc = color(ny)
|
||||
ny - ty match {
|
||||
case oy if oy >= 0 && oy < height =>
|
||||
val ol = buffer(oy)
|
||||
val oc = color(oy)
|
||||
for (nx <- dx0 to dx1 by sx) nx - tx match {
|
||||
case ox if ox >= 0 && ox < width => {
|
||||
changed = changed || (nl(nx) != ol(ox))
|
||||
changed = changed || (nl(nx) != ol(ox)) || (nc(nx) != oc(ox))
|
||||
nl(nx) = ol(ox)
|
||||
nc(nx) = oc(ox)
|
||||
}
|
||||
case _ => /* Got no source column. */
|
||||
}
|
||||
@ -118,19 +148,30 @@ class TextBuffer(var width: Int, var height: Int) {
|
||||
val h = nbt.getInteger("height")
|
||||
size = (w, h)
|
||||
val b = nbt.getTagList("buffer")
|
||||
for (i <- 0 until (h min b.tagCount())) {
|
||||
set(0, i, b.tagAt(i).asInstanceOf[NBTTagString].data)
|
||||
for (i <- 0 until (h min b.tagCount)) {
|
||||
val line = b.tagAt(i).asInstanceOf[NBTTagString].data
|
||||
set(0, i, line)
|
||||
}
|
||||
val c = nbt.getTagList("color")
|
||||
for (i <- 0 until (h min c.tagCount)) {
|
||||
val line = c.tagAt(i).asInstanceOf[NBTTagIntArray].intArray
|
||||
Array.copy(line, 0, color(i), 0, line.length min width)
|
||||
}
|
||||
}
|
||||
|
||||
def writeToNBT(nbt: NBTTagCompound): Unit = {
|
||||
nbt.setInteger("width", width)
|
||||
nbt.setInteger("height", height)
|
||||
val b = new NBTTagList
|
||||
val b = new NBTTagList()
|
||||
for (i <- 0 until height) {
|
||||
b.appendTag(new NBTTagString("", String.valueOf(buffer(i))))
|
||||
b.appendTag(new NBTTagString(null, String.valueOf(buffer(i))))
|
||||
}
|
||||
nbt.setTag("buffer", b)
|
||||
val c = new NBTTagList()
|
||||
for (i <- 0 until height) {
|
||||
c.appendTag(new NBTTagIntArray(null, color(i)))
|
||||
}
|
||||
nbt.setTag("color", c)
|
||||
}
|
||||
|
||||
override def toString = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user