mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-14 09:46:53 -04:00
Basic scrolling logic.
This commit is contained in:
parent
ca8f1e3b94
commit
bef070b9ff
@ -1,14 +1,29 @@
|
||||
package li.cil.oc.client.gui
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.client.Textures
|
||||
import li.cil.oc.util.PseudoMarkdown
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.Gui
|
||||
import net.minecraft.client.gui.GuiScreen
|
||||
import net.minecraft.client.gui.ScaledResolution
|
||||
import org.lwjgl.input.Mouse
|
||||
|
||||
class Manual extends GuiScreen {
|
||||
val document = PseudoMarkdown.parse( """# Headline
|
||||
var guiLeft = 0
|
||||
var guiTop = 0
|
||||
var xSize = 0
|
||||
var ySize = 0
|
||||
var offset = 0
|
||||
var documentHeight = 0
|
||||
final val documentMaxWidth = 230
|
||||
final val documentMaxHeight = 176
|
||||
final val scrollPosX = 244
|
||||
final val scrollPosY = 6
|
||||
final val scrollHeight = 180
|
||||
|
||||
val document = PseudoMarkdown.parse( """# Headline with more lines
|
||||
|
|
||||
|The Adapter block is the core of most of OpenComputers' mod integration.
|
||||
|
|
||||
@ -31,18 +46,60 @@ class Manual extends GuiScreen {
|
||||
|
|
||||
|And finally, [this is a link!](https://avatars1.githubusercontent.com/u/514903).""".stripMargin)
|
||||
|
||||
override def drawScreen(mouseX: Int, mouseY: Int, dt: Float): Unit = {
|
||||
def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
|
||||
|
||||
protected var scrollButton: ImageButton = _
|
||||
|
||||
override def doesGuiPauseGame = false
|
||||
|
||||
override def initGui(): Unit = {
|
||||
super.initGui()
|
||||
|
||||
val mc = Minecraft.getMinecraft
|
||||
val screenSize = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight)
|
||||
val guiSize = new ScaledResolution(mc, 256, 192)
|
||||
val (midX, midY) = (screenSize.getScaledWidth / 2, screenSize.getScaledHeight / 2)
|
||||
val (left, top) = (midX - guiSize.getScaledWidth / 2, midY - guiSize.getScaledHeight / 2)
|
||||
guiLeft = midX - guiSize.getScaledWidth / 2
|
||||
guiTop = midY - guiSize.getScaledHeight / 2
|
||||
xSize = guiSize.getScaledWidth
|
||||
ySize = guiSize.getScaledHeight
|
||||
offset = 0
|
||||
documentHeight = PseudoMarkdown.height(document, documentMaxWidth, fontRendererObj)
|
||||
|
||||
scrollButton = new ImageButton(1, guiLeft + scrollPosX, guiTop + scrollPosY, 6, 13, Textures.guiButtonScroll)
|
||||
add(buttonList, scrollButton)
|
||||
}
|
||||
|
||||
override def drawScreen(mouseX: Int, mouseY: Int, dt: Float): Unit = {
|
||||
mc.renderEngine.bindTexture(Textures.guiManual)
|
||||
Gui.func_146110_a(left, top, 0, 0, guiSize.getScaledWidth, guiSize.getScaledHeight, 256, 192)
|
||||
Gui.func_146110_a(guiLeft, guiTop, 0, 0, xSize, ySize, 256, 192)
|
||||
|
||||
super.drawScreen(mouseX, mouseY, dt)
|
||||
|
||||
PseudoMarkdown.render(document, left + 8, top + 8, 220, 176, 0, fontRendererObj)
|
||||
PseudoMarkdown.render(document, guiLeft + 8, guiTop + 8, documentMaxWidth, documentMaxHeight, offset, fontRendererObj)
|
||||
}
|
||||
|
||||
override def handleMouseInput(): Unit = {
|
||||
super.handleMouseInput()
|
||||
if (Mouse.hasWheel && Mouse.getEventDWheel != 0) {
|
||||
if (math.signum(Mouse.getEventDWheel) < 0) scrollDown()
|
||||
else scrollUp()
|
||||
}
|
||||
}
|
||||
|
||||
private def scrollUp() = scrollTo(offset - PseudoMarkdown.lineHeight(fontRendererObj) * 3)
|
||||
|
||||
private def scrollDown() = scrollTo(offset + PseudoMarkdown.lineHeight(fontRendererObj) * 3)
|
||||
|
||||
private def scrollTo(row: Int): Unit = {
|
||||
val maxOffset = documentHeight - documentMaxHeight
|
||||
offset = math.max(0, math.min(maxOffset, row))
|
||||
val yMin = guiTop + scrollPosY
|
||||
if (maxOffset > 0) {
|
||||
scrollButton.yPosition = yMin + (scrollHeight - 13) * offset / maxOffset
|
||||
}
|
||||
else {
|
||||
scrollButton.yPosition = yMin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,20 +27,50 @@ object PseudoMarkdown {
|
||||
* Renders a list of segments and tooltips if a segment with a tooltip is hovered.
|
||||
* Returns a link address if a link is hovered.
|
||||
*/
|
||||
def render(document: Iterable[Segment], x: Int, y: Int, maxWidth: Int, height: Int, offset: Int, renderer: FontRenderer): Option[String] = {
|
||||
def render(document: Iterable[Segment], x: Int, y: Int, maxWidth: Int, maxHeight: Int, yOffset: Int, renderer: FontRenderer): Option[String] = {
|
||||
GL11.glPushMatrix()
|
||||
GL11.glTranslatef(0, 0, 1)
|
||||
GL11.glDepthMask(true)
|
||||
GL11.glColor4f(0.01f, 0.01f, 0.01f, 1)
|
||||
GL11.glBegin(GL11.GL_QUADS)
|
||||
GL11.glVertex2f(x - 1, y - 1)
|
||||
GL11.glVertex2f(x - 1, y + 1 + maxHeight)
|
||||
GL11.glVertex2f(x + 1 + maxWidth, y + 1 + maxHeight)
|
||||
GL11.glVertex2f(x + 1 + maxWidth, y - 1)
|
||||
GL11.glEnd()
|
||||
|
||||
GL11.glDepthMask(false)
|
||||
GL11.glDepthFunc(GL11.GL_EQUAL)
|
||||
|
||||
var currentX = 0
|
||||
var currentY = 0
|
||||
for (segment <- document) {
|
||||
if (currentY >= offset) {
|
||||
segment.render(x, y + currentY, currentX, maxWidth, renderer)
|
||||
}
|
||||
currentY += segment.height(currentX, maxWidth, renderer) - renderer.FONT_HEIGHT
|
||||
segment.render(x, y + currentY - yOffset, currentX, maxWidth, maxHeight - (currentY - yOffset), renderer)
|
||||
currentY += segment.height(currentX, maxWidth, renderer) - lineHeight(renderer)
|
||||
currentX = segment.width(currentX, maxWidth, renderer)
|
||||
}
|
||||
|
||||
GL11.glDepthFunc(GL11.GL_LEQUAL)
|
||||
GL11.glPopMatrix()
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the overall height of a document, for computation of scroll offsets.
|
||||
*/
|
||||
def height(document: Iterable[Segment], maxWidth: Int, renderer: FontRenderer): Int = {
|
||||
var currentX = 0
|
||||
var currentY = 0
|
||||
for (segment <- document) {
|
||||
currentY += segment.height(currentX, maxWidth, renderer) - lineHeight(renderer)
|
||||
currentX = segment.width(currentX, maxWidth, renderer)
|
||||
}
|
||||
currentY
|
||||
}
|
||||
|
||||
def lineHeight(renderer: FontRenderer): Int = renderer.FONT_HEIGHT + 1
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
trait Segment {
|
||||
@ -66,7 +96,7 @@ object PseudoMarkdown {
|
||||
*/
|
||||
def width(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = 0
|
||||
|
||||
def render(x: Int, y: Int, indent: Int, width: Int, renderer: FontRenderer): Unit = {}
|
||||
def render(x: Int, y: Int, indent: Int, maxWidth: Int, maxHeight: Int, renderer: FontRenderer): Unit = {}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -107,7 +137,7 @@ object PseudoMarkdown {
|
||||
chars = chars.drop(lineChars)
|
||||
lineChars = maxChars(chars, maxWidth, renderer)
|
||||
}
|
||||
lines * renderer.FONT_HEIGHT
|
||||
lines * lineHeight(renderer)
|
||||
}
|
||||
|
||||
override def width(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = {
|
||||
@ -122,15 +152,15 @@ object PseudoMarkdown {
|
||||
currentX + renderer.getStringWidth(fullFormat + chars)
|
||||
}
|
||||
|
||||
override def render(x: Int, y: Int, indent: Int, maxWidth: Int, renderer: FontRenderer): Unit = {
|
||||
override def render(x: Int, y: Int, indent: Int, maxWidth: Int, maxHeight: Int, renderer: FontRenderer): Unit = {
|
||||
var currentX = x + indent
|
||||
var currentY = y
|
||||
var chars = text
|
||||
var numChars = maxChars(chars, maxWidth - indent, renderer)
|
||||
while (chars.length > 0) {
|
||||
renderer.drawString(fullFormat + chars.take(numChars), currentX, currentY, 0xFFFFFF)
|
||||
while (chars.length > 0 && (currentY - y) < maxHeight) {
|
||||
renderer.drawString(fullFormat + chars.take(numChars), currentX, currentY, 0xFAFAFA)
|
||||
currentX = x
|
||||
currentY += renderer.FONT_HEIGHT
|
||||
currentY += lineHeight(renderer)
|
||||
chars = chars.drop(numChars)
|
||||
numChars = maxChars(chars, maxWidth, renderer)
|
||||
}
|
||||
@ -147,13 +177,13 @@ object PseudoMarkdown {
|
||||
|
||||
private def maxChars(s: String, maxWidth: Int, renderer: FontRenderer): Int = {
|
||||
val breaks = Set(' ', '-', '.', '+', '*', '_', '/')
|
||||
var pos = 1
|
||||
var pos = 0
|
||||
var lastBreak = -1
|
||||
while (pos < s.length) {
|
||||
val width = stringWidth(fullFormat + s.take(pos), renderer)
|
||||
if (breaks.contains(s.charAt(pos))) lastBreak = pos
|
||||
if (width > maxWidth) return lastBreak + 1
|
||||
pos += 1
|
||||
val width = stringWidth(fullFormat + s.take(pos), renderer)
|
||||
if (width >= maxWidth) return lastBreak + 1
|
||||
if (pos < s.length && breaks.contains(s.charAt(pos))) lastBreak = pos
|
||||
}
|
||||
pos
|
||||
}
|
||||
@ -164,18 +194,18 @@ object PseudoMarkdown {
|
||||
private class HeaderSegment(parent: Segment, text: String, val level: Int) extends TextSegment(parent, text) {
|
||||
private def scale = math.max(2, 5 - level) / 2f
|
||||
|
||||
override protected def format = EnumChatFormatting.BOLD.toString
|
||||
override protected def format = EnumChatFormatting.UNDERLINE.toString
|
||||
|
||||
override protected def stringWidth(s: String, renderer: FontRenderer): Int = (super.stringWidth(s, renderer) * scale).toInt
|
||||
|
||||
override def height(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = (super.height(indent, maxWidth, renderer) * scale).toInt
|
||||
|
||||
override def render(x: Int, y: Int, indent: Int, maxWidth: Int, renderer: FontRenderer): Unit = {
|
||||
override def render(x: Int, y: Int, indent: Int, maxWidth: Int, maxHeight: Int, renderer: FontRenderer): Unit = {
|
||||
GL11.glPushMatrix()
|
||||
GL11.glTranslatef(x, y, 0)
|
||||
GL11.glScalef(scale, scale, scale)
|
||||
GL11.glTranslatef(-x, -y, 0)
|
||||
super.render(x, y, indent, maxWidth, renderer)
|
||||
super.render(x, y, indent, maxWidth, maxHeight, renderer)
|
||||
GL11.glPopMatrix()
|
||||
}
|
||||
|
||||
@ -211,7 +241,7 @@ object PseudoMarkdown {
|
||||
private class NewLineSegment extends Segment {
|
||||
override protected def parent: Segment = null
|
||||
|
||||
override def height(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = renderer.FONT_HEIGHT * 2
|
||||
override def height(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = lineHeight(renderer) * 2
|
||||
|
||||
override def toString: String = s"{NewLineSegment}"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user