From d7c084c0dd520c9c0d08e79bcc16e0c9e7eb6ad3 Mon Sep 17 00:00:00 2001 From: LeshaInc Date: Thu, 10 Jan 2019 17:13:13 +0200 Subject: [PATCH] Add nice frame to the screen --- .../ocelot/desktop/shader/general.frag | 2 +- .../resources/ocelot/desktop/spritesheet.png | Bin 0 -> 5724 bytes .../resources/ocelot/desktop/spritesheet.txt | 27 +++++++++++++ .../ocelot/desktop/graphics/Graphics.scala | 29 +++++++++++-- .../ocelot/desktop/graphics/Texture.scala | 27 +++++++++++++ .../scala/ocelot/desktop/ui/UiHandler.scala | 3 +- .../desktop/ui/widget/ScreenWidget.scala | 31 +++++++++----- .../ocelot/desktop/util/Spritesheet.scala | 38 ++++++++++++++++++ 8 files changed, 142 insertions(+), 15 deletions(-) create mode 100644 src/main/resources/ocelot/desktop/spritesheet.png create mode 100644 src/main/resources/ocelot/desktop/spritesheet.txt create mode 100644 src/main/scala/ocelot/desktop/util/Spritesheet.scala diff --git a/src/main/resources/ocelot/desktop/shader/general.frag b/src/main/resources/ocelot/desktop/shader/general.frag index 5fc8d2a..a345802 100644 --- a/src/main/resources/ocelot/desktop/shader/general.frag +++ b/src/main/resources/ocelot/desktop/shader/general.frag @@ -8,5 +8,5 @@ out vec4 outColor; uniform sampler2D uTexture; void main() { - outColor = fColor; + outColor = texture(uTexture, fUV) * fColor; } \ No newline at end of file diff --git a/src/main/resources/ocelot/desktop/spritesheet.png b/src/main/resources/ocelot/desktop/spritesheet.png new file mode 100644 index 0000000000000000000000000000000000000000..09dbe84b471b0782fa16c7695c438c61bc448492 GIT binary patch literal 5724 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 U0&Vzn`D+Y7D{CrMJ+=<}A0Yeo!2kdN literal 0 HcmV?d00001 diff --git a/src/main/resources/ocelot/desktop/spritesheet.txt b/src/main/resources/ocelot/desktop/spritesheet.txt new file mode 100644 index 0000000..7d78de6 --- /dev/null +++ b/src/main/resources/ocelot/desktop/spritesheet.txt @@ -0,0 +1,27 @@ +APU0 0 0 16 16 +APU1 16 0 16 16 +APU2 32 0 16 16 +BorderH 96 32 2 8 +BorderV 98 32 8 2 +CPU0 48 0 16 16 +CPU1 64 0 16 16 +CPU2 80 0 16 16 +CornerBL 64 32 8 8 +CornerBR 72 32 8 8 +CornerTL 80 32 8 8 +CornerTR 88 32 8 8 +EEPROM 96 0 16 16 +Empty 106 32 1 1 +GraphicsCard0 112 0 16 16 +GraphicsCard1 0 16 16 16 +GraphicsCard2 16 16 16 16 +HardDiskDrive0 32 16 16 16 +HardDiskDrive1 48 16 16 16 +HardDiskDrive2 64 16 16 16 +InternetCard 80 16 16 16 +Memory0 96 16 16 16 +Memory1 112 16 16 16 +Memory2 0 32 16 16 +Memory3 16 32 16 16 +Memory4 32 32 16 16 +Memory5 48 32 16 16 diff --git a/src/main/scala/ocelot/desktop/graphics/Graphics.scala b/src/main/scala/ocelot/desktop/graphics/Graphics.scala index 38adf71..7651fad 100644 --- a/src/main/scala/ocelot/desktop/graphics/Graphics.scala +++ b/src/main/scala/ocelot/desktop/graphics/Graphics.scala @@ -1,10 +1,10 @@ package ocelot.desktop.graphics -import ocelot.desktop.color.{Color, RGBAColorNorm} +import ocelot.desktop.color.{Color, IntColor, RGBAColorNorm} import ocelot.desktop.geometry.Transform2D import ocelot.desktop.graphics.mesh.{Mesh, MeshInstance} import ocelot.desktop.graphics.render.InstanceRenderer -import ocelot.desktop.util.FontLoader +import ocelot.desktop.util.{FontLoader, Spritesheet} import org.apache.logging.log4j.scala.Logging import org.lwjgl.opengl.GL11 @@ -24,6 +24,10 @@ class Graphics extends Logging { private var _background = RGBAColorNorm(0f, 0f, 0f, 1f) private var _fontSize: Float = 16f + private var _sprite: String = "Empty" + private var spriteRect = Spritesheet.sprites(_sprite) + private val emptySpriteTrans = Transform2D.translate(spriteRect.x, spriteRect.y) >> Transform2D.scale(spriteRect.w, spriteRect.h) + GL11.glEnable(GL11.GL_DEPTH_TEST) GL11.glDepthFunc(GL11.GL_LEQUAL) GL11.glEnable(GL11.GL_BLEND) @@ -74,6 +78,13 @@ class Graphics extends Logging { _fontSize = value } + def sprite: String = _sprite + + def sprite_=(value: String): Unit = { + _sprite = value + spriteRect = Spritesheet.sprites(_sprite) + } + def text(x: Float, y: Float, text: String): Unit = { var ox = x @@ -105,24 +116,34 @@ class Graphics extends Logging { // ^ dirty hack to avoid edge bleeding, somehow works ) - rectRenderer.schedule(MeshInstance(_background, z, Transform2D.translate(x, y) >> Transform2D.scale(width, height))) + rectRenderer.schedule(MeshInstance(_background, z, Transform2D.translate(x, y) >> Transform2D.scale(width, height), emptySpriteTrans)) textRenderer.schedule(MeshInstance(_foreground, z + 1, Transform2D.translate(x, y) >> Transform2D.scale(width, height), uvTransform)) z += 2 } + def sprite(name: String, x: Float, y: Float, width: Float, height: Float): Unit = { + flush() + sprite = name + background = RGBAColorNorm(1f, 1f, 1f, 1f) + rect(x, y, width, height) + } + def rect(x: Float, y: Float, width: Float, height: Float): Unit = { - rectRenderer.schedule(MeshInstance(_background, z, Transform2D.translate(x, y) >> Transform2D.scale(width, height))) + val uvTransform = Transform2D.translate(spriteRect.x, spriteRect.y) >> Transform2D.scale(spriteRect.w, spriteRect.h) + rectRenderer.schedule(MeshInstance(_background, z, Transform2D.translate(x, y) >> Transform2D.scale(width, height), uvTransform)) z += 1 } def flush(): Unit = { + Spritesheet.texture.bind() rectRenderer.flush() fontAtlas.bind() textRenderer.flush() } def commit(): Unit = { + Spritesheet.texture.bind() rectRenderer.commit() fontAtlas.bind() textRenderer.commit() diff --git a/src/main/scala/ocelot/desktop/graphics/Texture.scala b/src/main/scala/ocelot/desktop/graphics/Texture.scala index bd15042..8be0d9b 100644 --- a/src/main/scala/ocelot/desktop/graphics/Texture.scala +++ b/src/main/scala/ocelot/desktop/graphics/Texture.scala @@ -1,9 +1,11 @@ package ocelot.desktop.graphics +import java.awt.image.BufferedImage import java.nio.ByteBuffer import ocelot.desktop.util.{Resource, ResourceManager} import org.apache.logging.log4j.scala.Logging +import org.lwjgl.BufferUtils import org.lwjgl.opengl._ import org.lwjgl.system.MemoryUtil.NULL @@ -21,6 +23,31 @@ class Texture extends Logging with Resource { GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST) GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST) + def this(image: BufferedImage) { + this() + + val pixels = new Array[Int](image.getWidth * image.getHeight) + image.getRGB(0, 0, image.getWidth, image.getHeight, pixels, 0, image.getWidth) + + val buf = BufferUtils.createByteBuffer(image.getWidth * image.getHeight * 4) + + for (y <- 0 until image.getHeight) { + for (x <- 0 until image.getWidth) { + val pixel = pixels(y * image.getWidth + x) + buf.put(((pixel >> 16) & 0xFF).toByte) + buf.put(((pixel >> 8) & 0xFF).toByte) + buf.put((pixel & 0xFF).toByte) + buf.put(((pixel >> 24) & 0xFF).toByte) + } + } + + buf.flip() + + bind() + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, image.getWidth, image.getHeight, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf) + GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D) + } + def this(width: Int, height: Int, format: Int, dataType: Int) = { this() bind() diff --git a/src/main/scala/ocelot/desktop/ui/UiHandler.scala b/src/main/scala/ocelot/desktop/ui/UiHandler.scala index c5310e2..2b6b04d 100644 --- a/src/main/scala/ocelot/desktop/ui/UiHandler.scala +++ b/src/main/scala/ocelot/desktop/ui/UiHandler.scala @@ -5,7 +5,7 @@ import java.nio.{ByteBuffer, IntBuffer} import ocelot.desktop.geometry.{Size2D, Vector2D} import ocelot.desktop.graphics.Graphics import ocelot.desktop.ui.widget.RootWidget -import ocelot.desktop.util.{Audio, FPSCalculator, FontLoader} +import ocelot.desktop.util.{Audio, FPSCalculator, FontLoader, Spritesheet} import org.apache.logging.log4j.scala.Logging import org.lwjgl.glfw.{GLFW, GLFWErrorCallback} import org.lwjgl.openal._ @@ -75,6 +75,7 @@ class UiHandler(val root: RootWidget) extends Logging { logger.info(s"OpenGL renderer: ${GL11.glGetString(GL11.GL_RENDERER)}") FontLoader.init() + Spritesheet.load() graphics = new Graphics soundDevice = ALC10.alcOpenDevice(null.asInstanceOf[ByteBuffer]) diff --git a/src/main/scala/ocelot/desktop/ui/widget/ScreenWidget.scala b/src/main/scala/ocelot/desktop/ui/widget/ScreenWidget.scala index 5f8ad0b..125b66a 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/ScreenWidget.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/ScreenWidget.scala @@ -14,17 +14,17 @@ import scala.collection.mutable class ScreenWidget(screen: Screen) extends RootWidget with Logging { private val fontSize = 16f - var width = 80 - var height = 25 + var width = screen.getWidth + var height = screen.getHeight var background: Int = 0x000000 var foreground: Int = 0xFFFFFF private var data: Array[Cell] = Array.fill(width * height)(Cell(' ', background, foreground)) - override def minimumSize: Option[Size2D] = Some(Size2D(width * fontSize / 2f, height * fontSize)) + override def minimumSize: Option[Size2D] = Some(Size2D(width * fontSize / 2f + 32, height * fontSize + 32)) - override def maximumSize: Option[Size2D] = Some(Size2D(width * fontSize, height * fontSize * 2f)) + override def maximumSize: Option[Size2D] = minimumSize private var lastMousePos = Vector2D(0, 0) private var pressedMouseButtons = new mutable.HashSet[MouseEvent.Button.Value]() @@ -63,7 +63,7 @@ class ScreenWidget(screen: Screen) extends RootWidget with Logging { screen.mouseScroll(lastMousePos.x, lastMousePos.y, event.offset, User("myself")) } - def convertMousePos(p: Vector2D): Vector2D = Vector2D(p.x / fontSize * 2f, p.y / fontSize) + def convertMousePos(p: Vector2D): Vector2D = Vector2D((p.x - 16) / fontSize * 2f, (p.y - 16) / fontSize) override def update(): Unit = { val currentMousePos = convertMousePos(uiHandler.mousePosition) @@ -79,10 +79,14 @@ class ScreenWidget(screen: Screen) extends RootWidget with Logging { override def windowTitle: String = f"Ocelot Desktop [FPS: ${uiHandler.fps}%2.3f]" override def draw(g: Graphics): Unit = { - val tx = size.width / 2 - fontSize * width / 4 - val ty = size.height / 2 - fontSize * height / 2 + val w = math.round(fontSize * width / 2f) + 32 + val h = math.round(fontSize * height) + 32 + + g.clear(0, 0, w, h) + g.background = IntColor(0x333333) + g.sprite = "Empty" + g.rect(0, 0, w, h) - g.clear(0, 0, math.round(fontSize * width / 2f), math.round(fontSize * height)) g.fontSize = fontSize for (y <- 0 until height) { @@ -91,10 +95,19 @@ class ScreenWidget(screen: Screen) extends RootWidget with Logging { val Cell(char, bg, fg) = data(y * width + x) g.background = IntColor(bg) g.foreground = IntColor(fg) - g.char(tx + x * fontSize / 2f, ty + y * fontSize, char) + g.char(x * fontSize / 2f + 16, y * fontSize + 16, char) } } } + + g.sprite("CornerTL", 0, 0, 16,16) + g.sprite("CornerTR", w - 16, 0, 16,16) + g.sprite("CornerBL", 0, h - 16, 16,16) + g.sprite("CornerBR", w - 16, h - 16, 16,16) + g.sprite("BorderH", 16, 0, w - 32, 16) + g.sprite("BorderH", 16, h - 16, w - 32, 16) + g.sprite("BorderV", 0, 16, 16, h - 32) + g.sprite("BorderV", w - 16, 16, 16, h - 32) } def set(x: Int, y: Int, text: String, vertical: Boolean): Unit = { diff --git a/src/main/scala/ocelot/desktop/util/Spritesheet.scala b/src/main/scala/ocelot/desktop/util/Spritesheet.scala new file mode 100644 index 0000000..082e3d0 --- /dev/null +++ b/src/main/scala/ocelot/desktop/util/Spritesheet.scala @@ -0,0 +1,38 @@ +package ocelot.desktop.util + +import javax.imageio.ImageIO +import ocelot.desktop.graphics.Texture +import org.apache.logging.log4j.scala.Logging + +import scala.collection.mutable +import scala.io.Source + +object Spritesheet extends Logging { + val sprites = new mutable.HashMap[String, Rect]() + var texture: Texture = _ + + def load(): Unit = { + logger.info("Loading sprites") + + val imageURL = getClass.getResource("/ocelot/desktop/spritesheet.png") + val image = ImageIO.read(imageURL) + texture = new Texture(image) + + val txt = Source.fromURL(getClass.getResource("/ocelot/desktop/spritesheet.txt")) + + for (line <- txt.getLines) { + val split = line.split("\\s+") + sprites += (split.head -> Rect( + split(1).toFloat / image.getWidth.toFloat, + split(2).toFloat / image.getHeight.toFloat, + split(3).toFloat / image.getWidth.toFloat, + split(4).toFloat / image.getHeight.toFloat + )) + logger.info(s"${split.head} -> ${sprites(split.head)}") + } + + txt.close() + + logger.info(s"Loaded ${sprites.size} sprites") + } +}