Basic imager suppert, loading documents from resource.

This commit is contained in:
Florian Nücke 2015-04-08 09:37:50 +02:00
parent c1156aab38
commit c65142a059
4 changed files with 108 additions and 28 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

View File

@ -0,0 +1,22 @@
# Headline with more lines [with link](huehue) and *some* more
This is some test text for the subset of Markdown supported by the planned ingame documentation system for OpenComputers.
![opencomputers:transistor](../../textures/gui/button_power.png)
*This* is *italic* text, ~~strikethrough~~ maybe abc-ter **some** text **in bold**. Is _this underlined_? Oh, no, _it's also italic!_ Well, this \*isn't bold*.
## Smaller headline [also with *link* but this __one__ longer](huehue)
This is *italic
over two* lines. But *this ... no *this is* **_bold italic_** *text*.
### even smaller
*not italic *because ** why would it be*eh
isn't*.
# not a header
asdasd ![Hello There!](button_power.png) qweqwe
And finally, [this is a link!](https://avatars1.githubusercontent.com/u/514903).

View File

@ -2,15 +2,19 @@ package li.cil.oc.client.gui
import java.util import java.util
import com.google.common.base.Charsets
import li.cil.oc.Settings
import li.cil.oc.client.Textures import li.cil.oc.client.Textures
import li.cil.oc.util.PseudoMarkdown import li.cil.oc.util.PseudoMarkdown
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.gui.Gui import net.minecraft.client.gui.Gui
import net.minecraft.client.gui.GuiScreen import net.minecraft.client.gui.GuiScreen
import net.minecraft.client.gui.ScaledResolution import net.minecraft.client.gui.ScaledResolution
import net.minecraft.util.ResourceLocation
import org.lwjgl.input.Mouse import org.lwjgl.input.Mouse
import scala.collection.convert.WrapAsJava._ import scala.collection.convert.WrapAsJava._
import scala.io.Source
class Manual extends GuiScreen { class Manual extends GuiScreen {
var guiLeft = 0 var guiLeft = 0
@ -18,6 +22,7 @@ class Manual extends GuiScreen {
var xSize = 0 var xSize = 0
var ySize = 0 var ySize = 0
var offset = 0 var offset = 0
var document = Iterable.empty[PseudoMarkdown.Segment]
var documentHeight = 0 var documentHeight = 0
final val documentMaxWidth = 230 final val documentMaxWidth = 230
final val documentMaxHeight = 176 final val documentMaxHeight = 176
@ -25,33 +30,16 @@ class Manual extends GuiScreen {
final val scrollPosY = 6 final val scrollPosY = 6
final val scrollHeight = 180 final val scrollHeight = 180
val document = PseudoMarkdown.parse( """# Headline with more lines [with link](huehue) and *some* more
|
|This is some test text for the subset of Markdown supported by the planned ingame documentation system for OpenComputers.
|
|*This* is *italic* text, ~~strikethrough~~ maybe abc-ter **some** text **in bold**. Is _this underlined_? Oh, no, _it's also italic!_ Well, this \*isn't bold*.
|
|## Smaller headline [also with *link* but this __one__ longer](huehue)
|
|This is *italic
|over two* lines. But *this ... no *this is* **_bold italic_** *text*.
|
|### even smaller
|
|*not italic *because ** why would it be*eh
|
|isn't*.
|
| # not a header
|
|![](https://avatars1.githubusercontent.com/u/514903)
|
|And finally, [this is a link!](https://avatars1.githubusercontent.com/u/514903).""".stripMargin)
def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T]) def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
protected var scrollButton: ImageButton = _ protected var scrollButton: ImageButton = _
def loadPage(location: ResourceLocation): Iterator[String] = {
val resource = Minecraft.getMinecraft.getResourceManager.getResource(location)
val is = resource.getInputStream
Source.fromInputStream(is)(Charsets.UTF_8).getLines()
}
override def doesGuiPauseGame = false override def doesGuiPauseGame = false
override def initGui(): Unit = { override def initGui(): Unit = {
@ -66,6 +54,7 @@ class Manual extends GuiScreen {
xSize = guiSize.getScaledWidth xSize = guiSize.getScaledWidth
ySize = guiSize.getScaledHeight ySize = guiSize.getScaledHeight
offset = 0 offset = 0
document = PseudoMarkdown.parse(loadPage(new ResourceLocation(Settings.resourceDomain, "doc/index.md")))
documentHeight = PseudoMarkdown.height(document, documentMaxWidth, fontRendererObj) documentHeight = PseudoMarkdown.height(document, documentMaxWidth, fontRendererObj)
scrollButton = new ImageButton(1, guiLeft + scrollPosX, guiTop + scrollPosY, 6, 13, Textures.guiButtonScroll) scrollButton = new ImageButton(1, guiLeft + scrollPosX, guiTop + scrollPosY, 6, 13, Textures.guiButtonScroll)
@ -80,7 +69,7 @@ class Manual extends GuiScreen {
PseudoMarkdown.render(document, guiLeft + 8, guiTop + 8, documentMaxWidth, documentMaxHeight, offset, fontRendererObj, mouseX, mouseY) match { PseudoMarkdown.render(document, guiLeft + 8, guiTop + 8, documentMaxWidth, documentMaxHeight, offset, fontRendererObj, mouseX, mouseY) match {
case Some(segment) => segment.tooltip match { case Some(segment) => segment.tooltip match {
case Some(text) => drawHoveringText(seqAsJavaList(text.lines.toSeq), mouseX, mouseY, fontRendererObj) case Some(text) if text.nonEmpty => drawHoveringText(seqAsJavaList(text.lines.toSeq), mouseX, mouseY, fontRendererObj)
case _ => case _ =>
} }
case _ => case _ =>

View File

@ -1,7 +1,16 @@
package li.cil.oc.util package li.cil.oc.util
import java.io.InputStream
import javax.imageio.ImageIO
import li.cil.oc.Settings
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.FontRenderer import net.minecraft.client.gui.FontRenderer
import net.minecraft.client.renderer.texture.AbstractTexture
import net.minecraft.client.renderer.texture.TextureUtil
import net.minecraft.client.resources.IResourceManager
import net.minecraft.util.EnumChatFormatting import net.minecraft.util.EnumChatFormatting
import net.minecraft.util.ResourceLocation
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
import scala.annotation.tailrec import scala.annotation.tailrec
@ -16,8 +25,8 @@ object PseudoMarkdown {
/** /**
* Parses a plain text document into a list of segments. * Parses a plain text document into a list of segments.
*/ */
def parse(document: String): Iterable[Segment] = { def parse(document: Iterator[String]): Iterable[Segment] = {
var segments = document.lines.flatMap(line => Iterable(new TextSegment(null, line), new NewLineSegment())).toArray var segments = document.flatMap(line => Iterable(new TextSegment(null, line), new NewLineSegment())).toArray
for ((pattern, factory) <- segmentTypes) { for ((pattern, factory) <- segmentTypes) {
segments = segments.flatMap(_.refine(pattern, factory)) segments = segments.flatMap(_.refine(pattern, factory))
} }
@ -118,7 +127,7 @@ object PseudoMarkdown {
def link: Option[String] = None def link: Option[String] = None
private[PseudoMarkdown] def notifyHover(): Unit private[PseudoMarkdown] def notifyHover(): Unit = {}
private[PseudoMarkdown] def checkHovered(mouseX: Int, mouseY: Int, x: Int, y: Int, w: Int, h: Int): Option[InteractiveSegment] = if (mouseX >= x && mouseY >= y && mouseX <= x + w && mouseY <= y + h) Some(this) else None private[PseudoMarkdown] def checkHovered(mouseX: Int, mouseY: Int, x: Int, y: Int, w: Int, h: Int): Option[InteractiveSegment] = if (mouseX >= x && mouseY >= y && mouseX <= x + w && mouseY <= y + h) Some(this) else None
} }
@ -306,7 +315,45 @@ object PseudoMarkdown {
override def toString: String = s"{StrikethroughSegment: text = $text}" override def toString: String = s"{StrikethroughSegment: text = $text}"
} }
private class ImageSegment(val parent: Segment, val tooltip: String, val url: String) extends Segment { private class ImageSegment(val parent: Segment, val title: String, val url: String) extends InteractiveSegment {
val path = if (url.startsWith("/")) url else "doc/img/" + url
val location = new ResourceLocation(Settings.resourceDomain, path)
val texture = {
val manager = Minecraft.getMinecraft.getTextureManager
manager.getTexture(location) match {
case image: ImageTexture => image
case _ =>
val image = new ImageTexture(location)
manager.loadTexture(location, image)
image
}
}
override def tooltip: Option[String] = Option(title)
override def height(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = math.max(lineHeight(renderer), texture.height + 10 - lineHeight(renderer))
override def width(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = maxWidth
override def render(x: Int, y: Int, indent: Int, maxWidth: Int, maxHeight: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = {
Minecraft.getMinecraft.getTextureManager.bindTexture(location)
val xOffset = (maxWidth - texture.width) / 2
val yOffset = 4 + (if (indent > 0) lineHeight(renderer) else 0)
GL11.glColor4f(1, 1, 1, 1)
GL11.glBegin(GL11.GL_QUADS)
GL11.glTexCoord2f(0, 0)
GL11.glVertex2f(x + xOffset, y + yOffset)
GL11.glTexCoord2f(0, 1)
GL11.glVertex2f(x + xOffset, y + yOffset + texture.height)
GL11.glTexCoord2f(1, 1)
GL11.glVertex2f(x + xOffset + texture.width, y + yOffset + texture.height)
GL11.glTexCoord2f(1, 0)
GL11.glVertex2f(x + xOffset + texture.width, y + yOffset)
GL11.glEnd()
checkHovered(mouseX, mouseY, x + xOffset, y + yOffset, texture.width, texture.height)
}
override def toString: String = s"{ImageSegment: tooltip = $tooltip, url = $url}" override def toString: String = s"{ImageSegment: tooltip = $tooltip, url = $url}"
} }
@ -321,6 +368,28 @@ object PseudoMarkdown {
override def toString: String = s"{NewLineSegment}" override def toString: String = s"{NewLineSegment}"
} }
private class ImageTexture(val location: ResourceLocation) extends AbstractTexture {
var width = 0
var height = 0
override def loadTexture(manager: IResourceManager): Unit = {
deleteGlTexture()
var is: InputStream = null
try {
val resource = manager.getResource(location)
is = resource.getInputStream
val bi = ImageIO.read(is)
TextureUtil.uploadTextureImageAllocate(getGlTextureId, bi, false, false)
width = bi.getWidth
height = bi.getHeight
}
finally {
Option(is).foreach(_.close())
}
}
}
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
private def HeaderSegment(s: Segment, m: Regex.Match) = new HeaderSegment(s, m.group(2), m.group(1).length) private def HeaderSegment(s: Segment, m: Regex.Match) = new HeaderSegment(s, m.group(2), m.group(1).length)