mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-20 02:59:19 +01:00
Add nice frame to the screen
This commit is contained in:
parent
96e29edbf6
commit
d7c084c0dd
@ -8,5 +8,5 @@ out vec4 outColor;
|
||||
uniform sampler2D uTexture;
|
||||
|
||||
void main() {
|
||||
outColor = fColor;
|
||||
outColor = texture(uTexture, fUV) * fColor;
|
||||
}
|
||||
BIN
src/main/resources/ocelot/desktop/spritesheet.png
Normal file
BIN
src/main/resources/ocelot/desktop/spritesheet.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
27
src/main/resources/ocelot/desktop/spritesheet.txt
Normal file
27
src/main/resources/ocelot/desktop/spritesheet.txt
Normal file
@ -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
|
||||
@ -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()
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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])
|
||||
|
||||
@ -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 = {
|
||||
|
||||
38
src/main/scala/ocelot/desktop/util/Spritesheet.scala
Normal file
38
src/main/scala/ocelot/desktop/util/Spritesheet.scala
Normal file
@ -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")
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user