mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 02:24:05 +09:00
btex stuffs
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
<btex cover="hardcover" inner="standard" papersize="standard">
|
<btexdoc cover="hardcover" inner="standard" papersize="standard">
|
||||||
<cover>
|
<cover>
|
||||||
<title>The Way to Mastery of Lorem Ipsum<br />Or, How To Write and Publish a Book</title>
|
<title>The Way to Mastery of Lorem Ipsum<br />Or, How To Write and Publish a Book</title>
|
||||||
<author>Terran Publishing</author>
|
<author>Terran Publishing</author>
|
||||||
@@ -46,4 +46,4 @@
|
|||||||
<p>Typewriter and Printout are considered not bound and readers will only see one page at a time, while Hardcover is considered bound and two pages are presented to the readers.</p>
|
<p>Typewriter and Printout are considered not bound and readers will only see one page at a time, while Hardcover is considered bound and two pages are presented to the readers.</p>
|
||||||
|
|
||||||
</manuscript>
|
</manuscript>
|
||||||
</btex>
|
</btexdoc>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<btex def="examination">
|
<btexdoc def="examination">
|
||||||
<blocklut>
|
<blocklut>
|
||||||
<pair key="0" value="basegame:0" />
|
<pair key="0" value="basegame:0" />
|
||||||
<pair key="1" value="basegame:32" />
|
<pair key="1" value="basegame:32" />
|
||||||
@@ -54,4 +54,4 @@
|
|||||||
<p>Examination is a special format of the “book” that operates on the same book system.</p>
|
<p>Examination is a special format of the “book” that operates on the same book system.</p>
|
||||||
|
|
||||||
</manuscript>
|
</manuscript>
|
||||||
</btex>
|
</btexdoc>
|
||||||
|
|||||||
BIN
assets/mods/basegame/sprites/fixtures/musical_workbench.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/fixtures/musical_workbench.tga
LFS
Normal file
Binary file not shown.
BIN
lib/TerrarumSansBitmap.jar
LFS
BIN
lib/TerrarumSansBitmap.jar
LFS
Binary file not shown.
@@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
import net.torvald.terrarumsansbitmap.MovableType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-10-28.
|
* Created by minjaesong on 2023-10-28.
|
||||||
@@ -17,7 +18,9 @@ class BTeXDocument {
|
|||||||
var papersize = "standard"
|
var papersize = "standard"
|
||||||
|
|
||||||
var pageWidth = 420
|
var pageWidth = 420
|
||||||
var pageHeight = 25 * 24
|
var lineHeight = 24
|
||||||
|
var pageLines = 25
|
||||||
|
var pageHeight = pageLines * lineHeight
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val DEFAULT_PAGE_BACK = Color(0xe1e1d7ff.toInt())
|
val DEFAULT_PAGE_BACK = Color(0xe1e1d7ff.toInt())
|
||||||
@@ -61,13 +64,18 @@ class BTeXPage(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class MovableTypeDrawCall(val movableType: MovableType, val rowStart: Int, val rowEnd: Int) {
|
||||||
|
fun draw(batch: SpriteBatch, x: Float, y: Float) {
|
||||||
|
movableType.draw(batch, x, y, rowStart, rowEnd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class BTeXDrawCall(
|
class BTeXDrawCall(
|
||||||
val posX: Int,
|
val posX: Int,
|
||||||
val posY: Int,
|
val posY: Int,
|
||||||
val theme: String,
|
val theme: String,
|
||||||
val colour: Color,
|
val colour: Color,
|
||||||
val font: BitmapFont,
|
val text: MovableTypeDrawCall? = null,
|
||||||
val text: String? = null,
|
|
||||||
val texture: TextureRegion? = null,
|
val texture: TextureRegion? = null,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@@ -82,7 +90,7 @@ class BTeXDrawCall(
|
|||||||
batch.color = colour
|
batch.color = colour
|
||||||
|
|
||||||
if (text != null && texture == null) {
|
if (text != null && texture == null) {
|
||||||
font.draw(batch, text, px, py)
|
text.draw(batch, px, py)
|
||||||
}
|
}
|
||||||
else if (text == null && texture != null) {
|
else if (text == null && texture != null) {
|
||||||
batch.draw(texture, px, py)
|
batch.draw(texture, px, py)
|
||||||
|
|||||||
@@ -4,13 +4,16 @@ import com.badlogic.gdx.files.FileHandle
|
|||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.btex.BTeXDocument
|
import net.torvald.terrarum.btex.BTeXDocument
|
||||||
import net.torvald.terrarum.btex.BTeXDrawCall
|
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import org.xml.sax.Attributes
|
import org.xml.sax.Attributes
|
||||||
|
import org.xml.sax.InputSource
|
||||||
import org.xml.sax.helpers.DefaultHandler
|
import org.xml.sax.helpers.DefaultHandler
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.xml.parsers.SAXParserFactory
|
import javax.xml.parsers.SAXParserFactory
|
||||||
|
import kotlin.reflect.KFunction
|
||||||
|
import kotlin.reflect.full.declaredFunctions
|
||||||
|
import kotlin.reflect.full.findAnnotation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-10-28.
|
* Created by minjaesong on 2023-10-28.
|
||||||
@@ -27,18 +30,27 @@ object BTeXParser {
|
|||||||
return doc
|
return doc
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BTeXHandler(val doc: BTeXDocument) : DefaultHandler() {
|
operator fun invoke(string: String): BTeXDocument {
|
||||||
|
val doc = BTeXDocument()
|
||||||
|
val parser = SAXParserFactory.newDefaultInstance().newSAXParser()
|
||||||
|
parser.parse(InputSource(StringReader(string)), BTeXHandler(doc))
|
||||||
|
return doc
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class BTeXHandler(val doc: BTeXDocument) : DefaultHandler() {
|
||||||
private val DEFAULT_FONTCOL = Color(0x222222ff)
|
private val DEFAULT_FONTCOL = Color(0x222222ff)
|
||||||
private val LINE_HEIGHT = 24
|
private val LINE_HEIGHT = doc.lineHeight
|
||||||
|
|
||||||
private var cover = ""
|
private var cover = ""
|
||||||
private var inner = ""
|
private var inner = ""
|
||||||
private var papersize = ""
|
private var papersize = ""
|
||||||
private var def = ""
|
private var def = ""
|
||||||
|
|
||||||
private var pageWidth = 420
|
private var btexOpened = false
|
||||||
private var pageLines = 25
|
|
||||||
private var pageHeight = 25 * LINE_HEIGHT
|
private var pageWidth = doc.pageWidth
|
||||||
|
private var pageLines = doc.pageLines
|
||||||
|
private var pageHeight = doc.pageHeight
|
||||||
|
|
||||||
private val blockLut = HashMap<String, ItemID>()
|
private val blockLut = HashMap<String, ItemID>()
|
||||||
|
|
||||||
@@ -51,66 +63,93 @@ object BTeXParser {
|
|||||||
private var typeX = 0
|
private var typeX = 0
|
||||||
private var typeY = 0
|
private var typeY = 0
|
||||||
|
|
||||||
|
private val elemOpeners: HashMap<String, KFunction<*>> = HashMap()
|
||||||
|
private val elemClosers: HashMap<String, KFunction<*>> = HashMap()
|
||||||
|
|
||||||
|
init {
|
||||||
|
BTeXHandler::class.declaredFunctions.filter { it.findAnnotation<OpenTag>() != null }.forEach {
|
||||||
|
println("Tag opener: ${it.name}")
|
||||||
|
elemOpeners[it.name] = it
|
||||||
|
}
|
||||||
|
|
||||||
|
BTeXHandler::class.declaredFunctions.filter { it.findAnnotation<CloseTag>() != null }.forEach {
|
||||||
|
println("Tag closer: ${it.name}")
|
||||||
|
elemClosers[it.name] = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun printdbg(message: String?) {
|
||||||
|
val CSI = "\u001B[32m"
|
||||||
|
val timeNow = System.currentTimeMillis()
|
||||||
|
val ss = (timeNow / 1000) % 60
|
||||||
|
val mm = (timeNow / 60000) % 60
|
||||||
|
val hh = (timeNow / 3600000) % 24
|
||||||
|
val ms = timeNow % 1000
|
||||||
|
val out = this.javaClass.getSimpleName()
|
||||||
|
val prompt = CSI + String.format("%02d:%02d:%02d.%03d [%s]%s ", hh, mm, ss, ms, out, App.csi0)
|
||||||
|
if (message == null) {
|
||||||
|
println(prompt + "null")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val indentation = " ".repeat(out.length + 16)
|
||||||
|
val msgLines: Array<String> = message.toString().split("\\n".toRegex()).dropLastWhile { it.isEmpty() }
|
||||||
|
.toTypedArray()
|
||||||
|
for (i in msgLines.indices) {
|
||||||
|
println((if (i == 0) prompt else indentation) + msgLines[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) {
|
override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) {
|
||||||
val tag = qName; if (tagStack.isEmpty() && tag != "btex") throw BTeXParsingException("Document is not btex")
|
val tag = qName; if (tagStack.isEmpty() && tag.lowercase() != "btexdoc") throw BTeXParsingException("Document is not BTeX")
|
||||||
tagStack.add(tag)
|
tagStack.add(tag)
|
||||||
|
|
||||||
val attribs = HashMap<String, String>().also {
|
val attribs = HashMap<String, String>().also {
|
||||||
it.putAll((0 until attributes.length).map { attributes.getQName(it) to attributes.getValue(it) })
|
it.putAll((0 until attributes.length).map { attributes.getQName(it) to attributes.getValue(it) })
|
||||||
}
|
}
|
||||||
|
|
||||||
val mode = tagStack.getOrNull(1)
|
val theTag = tag.uppercase()
|
||||||
|
|
||||||
when (tag) {
|
elemOpeners["processElem$theTag"].let {
|
||||||
"btex" -> {
|
if (it == null)
|
||||||
if (attribs.containsKey("def"))
|
System.err.println("Unknown tag: $theTag")
|
||||||
def = attribs["def"]!!
|
else {
|
||||||
else {
|
try {
|
||||||
cover = attribs["cover"] ?: "printout"
|
it.call(this, this, doc, theTag, uri, attribs)
|
||||||
inner = attribs["inner"] ?: "standard"
|
}
|
||||||
papersize = attribs["papersize"] ?: "standard"
|
catch (e: Throwable) {
|
||||||
|
throw BTeXParsingException(e.stackTraceToString())
|
||||||
pageWidth = pageWidthMap[papersize]!!
|
|
||||||
pageLines = pageHeightMap[papersize]!!
|
|
||||||
pageHeight = pageLines * LINE_HEIGHT
|
|
||||||
|
|
||||||
doc.pageWidth = pageWidth
|
|
||||||
doc.pageHeight = pageHeight
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"pair" -> {
|
|
||||||
if (tagStack.size == 3 && mode == "blocklut") {
|
|
||||||
blockLut[attribs["key"]!!] = attribs["value"]!!
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw BTeXParsingException("<pair> used outside of <blocklut>")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"span" -> {
|
|
||||||
attribs["span"]?.let {
|
|
||||||
spanColour = it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printdbg("Start element \t($tag)")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun endElement(uri: String, localName: String, qName: String) {
|
override fun endElement(uri: String, localName: String, qName: String) {
|
||||||
tagStack.removeLast()
|
val popped = tagStack.removeLast()
|
||||||
|
|
||||||
when (qName) {
|
val theTag = qName.uppercase()
|
||||||
"span" -> {
|
|
||||||
spanColour = null
|
elemClosers["closeElem$theTag"].let {
|
||||||
|
try {
|
||||||
|
it?.call(this, this, doc, theTag, uri)
|
||||||
|
}
|
||||||
|
catch (e: Throwable) {
|
||||||
|
throw BTeXParsingException(e.stackTraceToString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printdbg(" End element \t($popped)")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun characters(ch: CharArray, start: Int, length: Int) {
|
override fun characters(ch: CharArray, start: Int, length: Int) {
|
||||||
val str = String(ch.sliceArray(start until start+length)).replace('\n',' ').replace(Regex(" +"), " ").trim()
|
val str =
|
||||||
val font = getFont()
|
String(ch.sliceArray(start until start + length)).replace('\n', ' ').replace(Regex(" +"), " ")//.trim()
|
||||||
advanceCursorPre(font.getWidth(str), 0)
|
|
||||||
doc.appendDrawCall(BTeXDrawCall(typeX, typeY, inner, getSpanColour(), font, str))
|
if (str.isNotBlank()) {
|
||||||
advanceCursorPost(font.getWidth(str), 0)
|
printdbg("Characters \t\"$str\"")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun advanceCursorPre(w: Int, h: Int) {
|
private fun advanceCursorPre(w: Int, h: Int) {
|
||||||
@@ -149,8 +188,99 @@ object BTeXParser {
|
|||||||
private val pageHeightMap = hashMapOf(
|
private val pageHeightMap = hashMapOf(
|
||||||
"standard" to 25
|
"standard" to 25
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
|
fun processElemBTEXDOC(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||||
|
if (handler.btexOpened) {
|
||||||
|
throw BTeXParsingException("BTEXDOC tag has already opened")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribs.containsKey("def"))
|
||||||
|
handler.def = attribs["def"]!!
|
||||||
|
else {
|
||||||
|
handler.cover = attribs["cover"] ?: "printout"
|
||||||
|
handler.inner = attribs["inner"] ?: "standard"
|
||||||
|
handler.papersize = attribs["papersize"] ?: "standard"
|
||||||
|
|
||||||
|
//change the "default values" of the document
|
||||||
|
handler.pageWidth = pageWidthMap[papersize]!!
|
||||||
|
handler.pageLines = pageHeightMap[papersize]!!
|
||||||
|
handler.pageHeight = pageLines * LINE_HEIGHT
|
||||||
|
|
||||||
|
doc.pageWidth = pageWidth
|
||||||
|
doc.pageHeight = pageHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.btexOpened = true
|
||||||
|
|
||||||
|
printdbg("BTeX document: def=${handler.def}, cover=${handler.cover}, inner=${handler.inner}, papersize=${handler.papersize}, dim=${handler.pageWidth}x${handler.pageHeight} (${handler.pageLines} lines)")
|
||||||
|
}
|
||||||
|
|
||||||
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
|
fun processElemPAIR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||||
|
if (tagStack.size == 3 && tagStack.getOrNull(1) == "blocklut") {
|
||||||
|
blockLut[attribs["key"]!!] = attribs["value"]!!
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw BTeXParsingException("<pair> used outside of <blocklut>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
|
fun processElemSPAN(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||||
|
attribs["span"]?.let {
|
||||||
|
spanColour = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
|
fun processElemTABLEOFCONTENTS(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||||
|
// TODO add post-parsing hook to the handler
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
|
fun processElemBR(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
|
fun processElemNEWPAGE(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
|
fun processElemP(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@CloseTag // reflective access is impossible with 'private'
|
||||||
|
fun closeElemP(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@OpenTag // reflective access is impossible with 'private'
|
||||||
|
fun processElemARST(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap<String, String>) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@CloseTag // reflective access is impossible with 'private'
|
||||||
|
fun closeElemSPAN(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String) {
|
||||||
|
spanColour = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private annotation class OpenTag
|
||||||
|
private annotation class CloseTag
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
$BULLET Terrarum Sans Bitmap
|
$BULLET Terrarum Sans Bitmap
|
||||||
|
|
||||||
© 2017-2024 Minjae Song ("CuriousTorvald") and the contributors
|
© 2017-2024 CuriousTorvald (minjaesong)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -58,6 +58,25 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
$BULLET LibGDX
|
||||||
|
|
||||||
|
This software contains modified version of the LibGDX.
|
||||||
|
|
||||||
|
© 2014-2023 LibGDX Contributors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$BULLET Joise
|
$BULLET Joise
|
||||||
|
|
||||||
@@ -125,7 +144,7 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|||||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
Kotlin translated and modified code Copyright (C) 2016 Minjaesong (CuriousTorvald)
|
Kotlin translated and modified code © 2016 CuriousTorvald (minjaesong)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -187,6 +206,32 @@ SOFTWARE.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$BULLET OKHsvUtil.kt contains source code originally written by Björn Ottosson
|
||||||
|
|
||||||
|
© 2021 Björn Ottosson
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
Kotlin translated and modified code © 2024 CuriousTorvald (minjaesong)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$BULLET GraalVM Community Edition
|
$BULLET GraalVM Community Edition
|
||||||
|
|
||||||
GraalVM Community Edition consists of multiple modules. The software as a whole,
|
GraalVM Community Edition consists of multiple modules. The software as a whole,
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import com.badlogic.gdx.utils.Disposable
|
|||||||
*/
|
*/
|
||||||
abstract class AudioBank : Disposable {
|
abstract class AudioBank : Disposable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the audio bank is a virtual instrument, set this property to `true`; if the audio bank reads audio
|
||||||
|
* sample directly from the disk, set it to `false`
|
||||||
|
*/
|
||||||
open val notCopyable: Boolean = false
|
open val notCopyable: Boolean = false
|
||||||
|
|
||||||
protected val hash = System.nanoTime()
|
protected val hash = System.nanoTime()
|
||||||
|
|||||||
@@ -67,16 +67,22 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (FloatArray,
|
|||||||
|
|
||||||
private val TAPS = 4 // 2*a tap lanczos intp. Lower = greater artefacts
|
private val TAPS = 4 // 2*a tap lanczos intp. Lower = greater artefacts
|
||||||
|
|
||||||
private val Lcache = HashMap<Long, Double>(1048576)
|
// private val Lcache = HashMap<Long, Double>(1048576)
|
||||||
fun L(x: Double): Double {
|
fun L(x: Double): Double {
|
||||||
return Lcache.getOrPut(x.toBits()) { // converting double to longbits allows faster cache lookup?!
|
/*return Lcache.getOrPut(x.toBits()) { // converting double to longbits allows faster cache lookup?!
|
||||||
if (x.absoluteValue < epsilon)
|
if (x.absoluteValue < epsilon)
|
||||||
1.0
|
1.0
|
||||||
else if (-TAPS <= x && x < TAPS)
|
else if (-TAPS <= x && x < TAPS)
|
||||||
(TAPS * sin(PI * x) * sin(PI * x / TAPS)) / (PI * PI * x * x)
|
(TAPS * sin(PI * x) * sin(PI * x / TAPS)) / (PI * PI * x * x)
|
||||||
else
|
else
|
||||||
0.0
|
0.0
|
||||||
}
|
}*/
|
||||||
|
return if (x.absoluteValue < epsilon)
|
||||||
|
1.0
|
||||||
|
else if (-TAPS <= x && x < TAPS)
|
||||||
|
(TAPS * sin(PI * x) * sin(PI * x / TAPS)) / (PI * PI * x * x)
|
||||||
|
else
|
||||||
|
0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
const val MP3_CHUNK_SIZE = 1152 // 1152 for 32k-48k, 576 for 16k-24k, 384 for 8k-12k
|
const val MP3_CHUNK_SIZE = 1152 // 1152 for 32k-48k, 576 for 16k-24k, 384 for 8k-12k
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.torvald.terrarum.modulebasegame
|
|||||||
|
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
|
import net.torvald.terrarum.modulebasegame.audio.audiobank.InstrumentLoader
|
||||||
import net.torvald.terrarum.modulebasegame.imagefont.WatchFont
|
import net.torvald.terrarum.modulebasegame.imagefont.WatchFont
|
||||||
import net.torvald.terrarum.weather.WeatherMixer
|
import net.torvald.terrarum.weather.WeatherMixer
|
||||||
|
|
||||||
@@ -42,6 +43,9 @@ class EntryPoint : ModuleEntryPoint() {
|
|||||||
WeatherCodex.weatherById["titlescreen"] =
|
WeatherCodex.weatherById["titlescreen"] =
|
||||||
WeatherCodex.getById("generic01")?.copy(identifier = "titlescreen", windSpeed = 1f) ?: WeatherMixer.DEFAULT_WEATHER
|
WeatherCodex.getById("generic01")?.copy(identifier = "titlescreen", windSpeed = 1f) ?: WeatherMixer.DEFAULT_WEATHER
|
||||||
|
|
||||||
|
// load virtual instruments
|
||||||
|
printdbg(this, "Loading virtual instrument 'spieluhr@41'")
|
||||||
|
InstrumentLoader.load("spieluhr", "basegame", "audio/effects/notes/spieluhr.ogg", 41)
|
||||||
|
|
||||||
if (App.IS_DEVELOPMENT_BUILD) {
|
if (App.IS_DEVELOPMENT_BUILD) {
|
||||||
println("[EntryPoint] Crafting Recipes: ")
|
println("[EntryPoint] Crafting Recipes: ")
|
||||||
|
|||||||
@@ -76,7 +76,8 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {})
|
|||||||
bufferR.fill(0f)
|
bufferR.fill(0f)
|
||||||
|
|
||||||
// only copy over the past and current messages
|
// only copy over the past and current messages
|
||||||
messageQueue.filter { it.tick <= tickCount }.forEach {
|
// use cloned version of queue to prevent concurrent modification exception
|
||||||
|
messageQueue.toMutableList().filter { it.tick <= tickCount }.forEach {
|
||||||
// copy over the samples
|
// copy over the samples
|
||||||
it.notes.forEach { note ->
|
it.notes.forEach { note ->
|
||||||
val noteSamples = getSample(note)
|
val noteSamples = getSample(note)
|
||||||
|
|||||||
233
src/net/torvald/terrarum/modulebasegame/gameactors/Bachomatic.kt
Normal file
233
src/net/torvald/terrarum/modulebasegame/gameactors/Bachomatic.kt
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.gameactors
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2024-04-18.
|
||||||
|
*/
|
||||||
|
interface Bachomatic {
|
||||||
|
|
||||||
|
operator fun invoke(): List<Long>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object PreludeInCMaj : Bachomatic {
|
||||||
|
|
||||||
|
private val TICK_DIVISOR = 10
|
||||||
|
|
||||||
|
override fun invoke() = List(16*TICK_DIVISOR) { 0L } +
|
||||||
|
prel(24,28,31,36,40) +
|
||||||
|
prel(24,26,33,38,41) +
|
||||||
|
prel(23,26,31,38,41) +
|
||||||
|
prel(24,28,31,36,40) +
|
||||||
|
prel(24,28,33,40,45) +
|
||||||
|
prel(24,26,30,33,38) +
|
||||||
|
prel(23,26,31,38,43) +
|
||||||
|
prel(23,24,28,31,36) +
|
||||||
|
prel(21,24,28,31,36) +
|
||||||
|
prel(14,21,26,30,36) +
|
||||||
|
prel(19,23,26,31,35) +
|
||||||
|
prel(19,22,28,31,37) +
|
||||||
|
prel(17,21,26,33,38) +
|
||||||
|
prel(17,20,26,29,35) +
|
||||||
|
prel(16,19,24,31,36) +
|
||||||
|
prel(16,17,21,24,29) +
|
||||||
|
prel(14,17,21,24,29) +
|
||||||
|
prel( 7,14,19,23,29) +
|
||||||
|
prel(12,16,19,24,28) +
|
||||||
|
prel(12,19,22,24,28) +
|
||||||
|
prel( 5,17,21,24,28) +
|
||||||
|
prel( 6,12,21,24,27) +
|
||||||
|
prel( 8,17,23,24,26) +
|
||||||
|
prel( 7,17,19,23,26) +
|
||||||
|
prel( 7,16,19,24,28) +
|
||||||
|
prel( 7,14,19,24,29) +
|
||||||
|
prel( 7,14,19,23,29) +
|
||||||
|
prel( 7,15,21,24,30) +
|
||||||
|
prel( 7,16,19,24,31) +
|
||||||
|
prel( 7,14,19,24,29) +
|
||||||
|
prel( 7,14,19,23,29) +
|
||||||
|
prel( 0,12,19,22,28) +
|
||||||
|
end1( 0,12,17,21,24,29,21,17,14) +
|
||||||
|
end2( 0,11,31,35,38,41,26,29,28) +
|
||||||
|
end3( 0,12,28,31,36) + List(16*TICK_DIVISOR - 5) { 0L }
|
||||||
|
|
||||||
|
private fun prel(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): List<Long> {
|
||||||
|
return toPianoRoll(
|
||||||
|
1L shl n1 to TICK_DIVISOR+2, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR-1,
|
||||||
|
1L shl n5 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR,
|
||||||
|
1L shl n1 to TICK_DIVISOR, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR-1,
|
||||||
|
1L shl n5 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun end1(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int, n6: Int, n7: Int, n8: Int, n9: Int): List<Long> {
|
||||||
|
return toPianoRoll(
|
||||||
|
1L shl n1 to TICK_DIVISOR+2, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR-1,
|
||||||
|
1L shl n5 to TICK_DIVISOR, 1L shl n6 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR,
|
||||||
|
1L shl n5 to TICK_DIVISOR, 1L shl n7 to TICK_DIVISOR, 1L shl n8 to TICK_DIVISOR, 1L shl n7 to TICK_DIVISOR-1,
|
||||||
|
1L shl n8 to TICK_DIVISOR, 1L shl n9 to TICK_DIVISOR, 1L shl n8 to TICK_DIVISOR, 1L shl n9 to TICK_DIVISOR)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun end2(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int, n6: Int, n7: Int, n8: Int, n9: Int): List<Long> {
|
||||||
|
return toPianoRoll(
|
||||||
|
1L shl n1 to TICK_DIVISOR+2, 1L shl n2 to TICK_DIVISOR+1, 1L shl n3 to TICK_DIVISOR+1, 1L shl n4 to TICK_DIVISOR+1,
|
||||||
|
1L shl n5 to TICK_DIVISOR+1, 1L shl n6 to TICK_DIVISOR+2, 1L shl n5 to TICK_DIVISOR+2, 1L shl n4 to TICK_DIVISOR+2,
|
||||||
|
1L shl n5 to TICK_DIVISOR+3, 1L shl n4 to TICK_DIVISOR+3, 1L shl n3 to TICK_DIVISOR+4, 1L shl n4 to TICK_DIVISOR+4,
|
||||||
|
1L shl n7 to TICK_DIVISOR+6, 1L shl n8 to TICK_DIVISOR+8, 1L shl n9 to TICK_DIVISOR+12, 1L shl n7 to TICK_DIVISOR+24)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun end3(vararg ns: Int): List<Long> {
|
||||||
|
return ns.map { 1L shl it } // arpeggiate
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toPianoRoll(vararg noteAndLen: Pair<Long, Int>): List<Long> {
|
||||||
|
val ret = MutableList<Long>(noteAndLen.sumOf { it.second }) { 0 }
|
||||||
|
var c = 0
|
||||||
|
noteAndLen.forEach { (note, len) ->
|
||||||
|
ret[c] = note
|
||||||
|
c += len
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toPianoRoll(vararg notes: Long) = List<Long>(notes.size * TICK_DIVISOR) {
|
||||||
|
if (it % TICK_DIVISOR == 0) notes[it / TICK_DIVISOR] else 0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object PreludeInCshMaj : Bachomatic {
|
||||||
|
private val TICK_DIVISOR = 8
|
||||||
|
|
||||||
|
private val TICK_GAP = List(TICK_DIVISOR - 1) { 0L }
|
||||||
|
|
||||||
|
override fun invoke() = List(16* TICK_DIVISOR) { 0L } +
|
||||||
|
n321232(32,37,41,13,25) +
|
||||||
|
n121212(37,42,15,25) +
|
||||||
|
n121212(37,44,17,25) +
|
||||||
|
n121212(37,46,18,25) +
|
||||||
|
n121212(37,44,17,25) +
|
||||||
|
n321231(39,41,42,15,24) +
|
||||||
|
n321231(37,39,41,13,25) +
|
||||||
|
tqSSSS454321(34,36,37,39,41,20,22,24) +
|
||||||
|
|
||||||
|
p321232(15,20,24,32,44) +
|
||||||
|
p121212(20,25,34,44) +
|
||||||
|
p121212(20,27,36,44) +
|
||||||
|
p121212(20,29,37,44) +
|
||||||
|
p121212(20,27,36,44) +
|
||||||
|
p321231(22,24,25,32,43) +
|
||||||
|
p321231(20,22,24,32,44) +
|
||||||
|
tqSSSS454321(17,18,20,22,23,39,41,42) +
|
||||||
|
|
||||||
|
n321232(34,39,42,15,27) +
|
||||||
|
n121212(39,44,17,27) +
|
||||||
|
n121212(39,46,18,27) +
|
||||||
|
n121212(39,47,20,27) +
|
||||||
|
n121212(39,46,18,27) +
|
||||||
|
n321231(41,42,44,17,26) +
|
||||||
|
n321231(39,41,42,15,27) +
|
||||||
|
tqSSSS454321(36,37,39,41,42,22,24,25) +
|
||||||
|
|
||||||
|
p321232(17,22,25,34,46) +
|
||||||
|
p121212(22,27,36,46) +
|
||||||
|
p121212(22,29,37,46) +
|
||||||
|
p121212(22,30,39,46) +
|
||||||
|
p121212(22,29,37,46) +
|
||||||
|
p321231(24,25,27,36,45) +
|
||||||
|
p321231(22,24,25,34,46) +
|
||||||
|
tqQQ321231(24,26,28,44,43) +
|
||||||
|
|
||||||
|
tQQQ212321b(28,29,31,44,32,44) +
|
||||||
|
tqQQ321231(22,24,26,43,41) +
|
||||||
|
tQQQ212321(39,41,42,27,15,27) +
|
||||||
|
tqQQ321231(41,43,45,25,24) +
|
||||||
|
tQQQ212321b(45,46,48,25,13,25) +
|
||||||
|
tqQQ321231(39,41,43,24,22) +
|
||||||
|
tQQQ321231(20,22,24,44,32,44) +
|
||||||
|
|
||||||
|
/* 40 */
|
||||||
|
tqQQ321231(22,24,26,42,41) +
|
||||||
|
tQQQ212321b(26,27,29,42,37,42) +
|
||||||
|
tqQQ321231(20,22,24,41,39) +
|
||||||
|
tQQQ321231(37,39,41,25,13,25) +
|
||||||
|
tqQQ321231(39,41,43,28,27) +
|
||||||
|
tQQQ212321b(43,44,46,23,11,23) +
|
||||||
|
tqQQ321231(37,39,41,22,20) +
|
||||||
|
|
||||||
|
/* 47 */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
List(16* TICK_DIVISOR) { 0L }
|
||||||
|
|
||||||
|
private fun n321232(n1: Int, n2: Int, n3: Int, p1: Int, p2: Int) =
|
||||||
|
listOf((1L shl n3) or (1L shl p1)) + TICK_GAP +
|
||||||
|
listOf( 1L shl n2) + TICK_GAP +
|
||||||
|
listOf( 1L shl n1) + TICK_GAP +
|
||||||
|
listOf( 1L shl n2) + TICK_GAP +
|
||||||
|
listOf((1L shl n3) or (1L shl p2)) + TICK_GAP +
|
||||||
|
listOf( 1L shl n2) + TICK_GAP
|
||||||
|
|
||||||
|
private fun n321231(n1: Int, n2: Int, n3: Int, p1: Int, p2: Int) =
|
||||||
|
listOf((1L shl n3) or (1L shl p1)) + TICK_GAP +
|
||||||
|
listOf( 1L shl n2) + TICK_GAP +
|
||||||
|
listOf( 1L shl n1) + TICK_GAP +
|
||||||
|
listOf( 1L shl n2) + TICK_GAP +
|
||||||
|
listOf((1L shl n3) or (1L shl p2)) + TICK_GAP +
|
||||||
|
listOf( 1L shl n1) + TICK_GAP
|
||||||
|
|
||||||
|
private fun n121212(n1: Int, n2: Int, p1: Int, p2: Int) =
|
||||||
|
listOf((1L shl n2) or (1L shl p1)) + TICK_GAP +
|
||||||
|
listOf( 1L shl n1) + TICK_GAP +
|
||||||
|
listOf( 1L shl n2) + TICK_GAP +
|
||||||
|
listOf( 1L shl n1) + TICK_GAP +
|
||||||
|
listOf((1L shl n2) or (1L shl p2)) + TICK_GAP +
|
||||||
|
listOf( 1L shl n1) + TICK_GAP
|
||||||
|
|
||||||
|
private fun tqSSSS454321(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int, p1: Int, p2: Int, p3: Int) =
|
||||||
|
listOf( 1L shl n4) + TICK_GAP +
|
||||||
|
listOf( 1L shl n5) + TICK_GAP +
|
||||||
|
listOf((1L shl n4) or (1L shl p3)) + TICK_GAP +
|
||||||
|
listOf((1L shl n3) or (1L shl p2)) + TICK_GAP +
|
||||||
|
listOf((1L shl n2) or (1L shl p1)) + TICK_GAP +
|
||||||
|
listOf((1L shl n1) or (1L shl p2)) + TICK_GAP
|
||||||
|
|
||||||
|
|
||||||
|
private fun p321232(n1: Int, n2: Int, n3: Int, p1: Int, p2: Int) = n321232(n1, n2, n3, p1, p2)
|
||||||
|
private fun p321231(n1: Int, n2: Int, n3: Int, p1: Int, p2: Int) = n321231(n1, n2, n3, p1, p2)
|
||||||
|
private fun p121212(n1: Int, n2: Int, p1: Int, p2: Int) = n121212(n1, n2, p1, p2)
|
||||||
|
|
||||||
|
private fun tqQQ321231(p1: Int, p2: Int, p3: Int, n1: Int, n2: Int) =
|
||||||
|
listOf( 1L shl p3) + TICK_GAP +
|
||||||
|
listOf( 1L shl p2) + TICK_GAP +
|
||||||
|
listOf((1L shl p1) or (1L shl n1)) + TICK_GAP +
|
||||||
|
listOf( 1L shl p2) + TICK_GAP +
|
||||||
|
listOf((1L shl p3) or (1L shl n2)) + TICK_GAP +
|
||||||
|
listOf( 1L shl p1) + TICK_GAP
|
||||||
|
|
||||||
|
private fun tQQQ321231(p1: Int, p2: Int, p3: Int, n1: Int, n2: Int, n3: Int) =
|
||||||
|
listOf((1L shl p3) or (1L shl n1)) + TICK_GAP +
|
||||||
|
listOf( 1L shl p2) + TICK_GAP +
|
||||||
|
listOf((1L shl p1) or (1L shl n2)) + TICK_GAP +
|
||||||
|
listOf( 1L shl p2) + TICK_GAP +
|
||||||
|
listOf((1L shl p3) or (1L shl n3)) + TICK_GAP +
|
||||||
|
listOf( 1L shl p1) + TICK_GAP
|
||||||
|
|
||||||
|
private fun tQQQ212321b(p1: Int, p2: Int, p3: Int, n1: Int, n2: Int, n3: Int) =
|
||||||
|
listOf((1L shl p2) or (1L shl n1)) + TICK_GAP +
|
||||||
|
listOf( 1L shl p1) + TICK_GAP +
|
||||||
|
listOf((1L shl p2) or (1L shl n2)) + TICK_GAP +
|
||||||
|
listOf( 1L shl p3) + TICK_GAP +
|
||||||
|
listOf((1L shl p2) or (1L shl n3)) + TICK_GAP +
|
||||||
|
listOf( 1L shl(p1-1)) + TICK_GAP
|
||||||
|
|
||||||
|
private fun tQQQ212321(p1: Int, p2: Int, p3: Int, n1: Int, n2: Int, n3: Int) =
|
||||||
|
listOf((1L shl p2) or (1L shl n1)) + TICK_GAP +
|
||||||
|
listOf( 1L shl p1) + TICK_GAP +
|
||||||
|
listOf((1L shl p2) or (1L shl n2)) + TICK_GAP +
|
||||||
|
listOf( 1L shl p3) + TICK_GAP +
|
||||||
|
listOf((1L shl p2) or (1L shl n3)) + TICK_GAP +
|
||||||
|
listOf( 1L shl p1) + TICK_GAP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,15 +1,12 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.gameactors
|
package net.torvald.terrarum.modulebasegame.gameactors
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import com.jme3.math.FastMath.DEG_TO_RAD
|
import com.jme3.math.FastMath.DEG_TO_RAD
|
||||||
import net.torvald.colourutil.HUSLColorConverter
|
|
||||||
import net.torvald.colourutil.OKHsv
|
import net.torvald.colourutil.OKHsv
|
||||||
import net.torvald.colourutil.toColor
|
import net.torvald.colourutil.toColor
|
||||||
import net.torvald.colourutil.tosRGB
|
import net.torvald.colourutil.tosRGB
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.App.printdbg
|
|
||||||
import net.torvald.terrarum.CommonResourcePool
|
import net.torvald.terrarum.CommonResourcePool
|
||||||
import net.torvald.terrarum.INGAME
|
import net.torvald.terrarum.INGAME
|
||||||
import net.torvald.terrarum.ModMgr
|
import net.torvald.terrarum.ModMgr
|
||||||
@@ -22,7 +19,6 @@ import net.torvald.terrarum.modulebasegame.audio.audiobank.AudioBankMusicBox
|
|||||||
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
|
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
import kotlin.math.pow
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2024-04-15.
|
* Created by minjaesong on 2024-04-15.
|
||||||
@@ -92,99 +88,18 @@ class FixtureMechanicalTines : Electric {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun findSetBits(num: Long): List<Int> {
|
|
||||||
val result = mutableListOf<Int>()
|
|
||||||
for (i in 0 until 61) {
|
|
||||||
if (num and (1L shl i) != 0L) {
|
|
||||||
result.add(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient private val TICK_DIVISOR = 10
|
@Transient val testNotes = PreludeInCshMaj()
|
||||||
|
|
||||||
@Transient val testNotes = List(16*TICK_DIVISOR) { 0L } +
|
fun findSetBits(num: Long): List<Int> {
|
||||||
prel(24,28,31,36,40) +
|
val result = mutableListOf<Int>()
|
||||||
prel(24,26,33,38,41) +
|
for (i in 0 until 61) {
|
||||||
prel(23,26,31,38,41) +
|
if (num and (1L shl i) != 0L) {
|
||||||
prel(24,28,31,36,40) +
|
result.add(i)
|
||||||
prel(24,28,33,40,45) +
|
}
|
||||||
prel(24,26,30,33,38) +
|
|
||||||
prel(23,26,31,38,43) +
|
|
||||||
prel(23,24,28,31,36) +
|
|
||||||
prel(21,24,28,31,36) +
|
|
||||||
prel(14,21,26,30,36) +
|
|
||||||
prel(19,23,26,31,35) +
|
|
||||||
prel(19,22,28,31,37) +
|
|
||||||
prel(17,21,26,33,38) +
|
|
||||||
prel(17,20,26,29,35) +
|
|
||||||
prel(16,19,24,31,36) +
|
|
||||||
prel(16,17,21,24,29) +
|
|
||||||
prel(14,17,21,24,29) +
|
|
||||||
prel( 7,14,19,23,29) +
|
|
||||||
prel(12,16,19,24,28) +
|
|
||||||
prel(12,19,22,24,28) +
|
|
||||||
prel( 5,17,21,24,28) +
|
|
||||||
prel( 6,12,21,24,27) +
|
|
||||||
prel( 8,17,23,24,26) +
|
|
||||||
prel( 7,17,19,23,26) +
|
|
||||||
prel( 7,16,19,24,28) +
|
|
||||||
prel( 7,14,19,24,29) +
|
|
||||||
prel( 7,14,19,23,29) +
|
|
||||||
prel( 7,15,21,24,30) +
|
|
||||||
prel( 7,16,19,24,31) +
|
|
||||||
prel( 7,14,19,24,29) +
|
|
||||||
prel( 7,14,19,23,29) +
|
|
||||||
prel( 0,12,19,22,28) +
|
|
||||||
end1( 0,12,17,21,24,29,21,17,14) +
|
|
||||||
end2( 0,11,31,35,38,41,26,29,28) +
|
|
||||||
end3( 0,12,28,31,36) + List(16*TICK_DIVISOR - 5) { 0L }
|
|
||||||
|
|
||||||
private fun prel(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): List<Long> {
|
|
||||||
return toPianoRoll(
|
|
||||||
1L shl n1 to TICK_DIVISOR+2, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR-1,
|
|
||||||
1L shl n5 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR,
|
|
||||||
1L shl n1 to TICK_DIVISOR, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR-1,
|
|
||||||
1L shl n5 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun end1(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int, n6: Int, n7: Int, n8: Int, n9: Int): List<Long> {
|
|
||||||
return toPianoRoll(
|
|
||||||
1L shl n1 to TICK_DIVISOR+2, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR-1,
|
|
||||||
1L shl n5 to TICK_DIVISOR, 1L shl n6 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR,
|
|
||||||
1L shl n5 to TICK_DIVISOR, 1L shl n7 to TICK_DIVISOR, 1L shl n8 to TICK_DIVISOR, 1L shl n7 to TICK_DIVISOR-1,
|
|
||||||
1L shl n8 to TICK_DIVISOR, 1L shl n9 to TICK_DIVISOR, 1L shl n8 to TICK_DIVISOR, 1L shl n9 to TICK_DIVISOR)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun end2(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int, n6: Int, n7: Int, n8: Int, n9: Int): List<Long> {
|
|
||||||
return toPianoRoll(
|
|
||||||
1L shl n1 to TICK_DIVISOR+2, 1L shl n2 to TICK_DIVISOR+1, 1L shl n3 to TICK_DIVISOR+1, 1L shl n4 to TICK_DIVISOR+1,
|
|
||||||
1L shl n5 to TICK_DIVISOR+1, 1L shl n6 to TICK_DIVISOR+2, 1L shl n5 to TICK_DIVISOR+2, 1L shl n4 to TICK_DIVISOR+2,
|
|
||||||
1L shl n5 to TICK_DIVISOR+3, 1L shl n4 to TICK_DIVISOR+3, 1L shl n3 to TICK_DIVISOR+4, 1L shl n4 to TICK_DIVISOR+4,
|
|
||||||
1L shl n7 to TICK_DIVISOR+6, 1L shl n8 to TICK_DIVISOR+8, 1L shl n9 to TICK_DIVISOR+12, 1L shl n7 to TICK_DIVISOR+24)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun end3(vararg ns: Int): List<Long> {
|
|
||||||
return ns.map { 1L shl it } // arpeggiate
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun toPianoRoll(vararg noteAndLen: Pair<Long, Int>): List<Long> {
|
|
||||||
val ret = MutableList<Long>(noteAndLen.sumOf { it.second }) { 0 }
|
|
||||||
var c = 0
|
|
||||||
noteAndLen.forEach { (note, len) ->
|
|
||||||
ret[c] = note
|
|
||||||
c += len
|
|
||||||
}
|
}
|
||||||
return ret
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toPianoRoll(vararg notes: Long) = List<Long>(notes.size * TICK_DIVISOR) {
|
|
||||||
if (it % TICK_DIVISOR == 0) notes[it / TICK_DIVISOR] else 0
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import net.torvald.terrarum.langpack.Lang
|
|||||||
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
|
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UICrafting
|
import net.torvald.terrarum.modulebasegame.ui.UICrafting
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIEngravingTextSign
|
import net.torvald.terrarum.modulebasegame.ui.UIEngravingTextSign
|
||||||
|
import net.torvald.terrarum.modulebasegame.ui.UIMusicalWorkbench
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,3 +87,28 @@ class FixtureEngravingWorkbench : FixtureBase, CraftingStation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2024-04-22.
|
||||||
|
*/
|
||||||
|
class FixtureMusicalWorkbench : FixtureBase, CraftingStation {
|
||||||
|
|
||||||
|
@Transient override val tags = listOf("musicbox")
|
||||||
|
|
||||||
|
constructor() : super(
|
||||||
|
BlockBox(BlockBox.NO_COLLISION, 2, 2),
|
||||||
|
nameFun = { Lang["ITEM_MUSICAL_WORKBENCH"] },
|
||||||
|
mainUI = UIMusicalWorkbench()
|
||||||
|
) {
|
||||||
|
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/musical_workbench.tga")
|
||||||
|
|
||||||
|
density = BlockCodex[Block.PLANK_NORMAL].density.toDouble()
|
||||||
|
setHitboxDimension(itemImage.texture.width, itemImage.texture.height, 0, 0)
|
||||||
|
|
||||||
|
makeNewSprite(TextureRegionPack(itemImage.texture, 32, 32)).let {
|
||||||
|
it.setRowsAndFrames(1,1)
|
||||||
|
}
|
||||||
|
|
||||||
|
actorValue[AVKey.BASEMASS] = 40.0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.ui
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import net.torvald.terrarum.modulebasegame.gameactors.FixtureMechanicalTines.Companion.findSetBits
|
||||||
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2024-04-22.
|
||||||
|
*/
|
||||||
|
class UIMusicalWorkbench : UICanvas(
|
||||||
|
toggleKeyLiteral = "control_key_inventory",
|
||||||
|
toggleButtonLiteral = "control_gamepad_start"
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class ComposerRow(
|
||||||
|
var notes: Long,
|
||||||
|
var len: Int,
|
||||||
|
var arp: Int // 0: none, 1: up, 2: down
|
||||||
|
) {
|
||||||
|
fun toPunchedNotes(): List<Long> {
|
||||||
|
val ret = MutableList<Long>(len) { 0L }
|
||||||
|
|
||||||
|
when (arp) {
|
||||||
|
0 -> { ret[0] = notes }
|
||||||
|
1, 2 -> {
|
||||||
|
val arpNotes = findSetBits(notes).let { if (arp == 2) it.reversed() else it }
|
||||||
|
|
||||||
|
for (i in 0 until minOf(len, arpNotes.size)) {
|
||||||
|
ret[i] = 1L shl arpNotes[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val rowBuf = ArrayList<ComposerRow>()
|
||||||
|
override var width: Int
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
set(value) {}
|
||||||
|
override var height: Int
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
set(value) {}
|
||||||
|
|
||||||
|
override fun updateImpl(delta: Float) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renderImpl(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.torvald.terrarum.tests
|
package net.torvald.terrarum.tests
|
||||||
|
|
||||||
|
import net.torvald.btex.BTeXParser
|
||||||
import org.xml.sax.Attributes
|
import org.xml.sax.Attributes
|
||||||
import org.xml.sax.HandlerBase
|
import org.xml.sax.HandlerBase
|
||||||
import org.xml.sax.helpers.DefaultHandler
|
import org.xml.sax.helpers.DefaultHandler
|
||||||
@@ -16,7 +17,7 @@ fun main() {
|
|||||||
val csiG = "\u001B[32m"
|
val csiG = "\u001B[32m"
|
||||||
val csi0 = "\u001B[m"
|
val csi0 = "\u001B[m"
|
||||||
|
|
||||||
val tex = """<btex cover="hardcover" inner="standard" papersize="standard">
|
val tex = """<btexdoc cover="hardcover" inner="standard" papersize="standard">
|
||||||
<cover>
|
<cover>
|
||||||
<title>The Way to Mastery of Lorem Ipsum<br />Or, How To Write and Publish a Book</title>
|
<title>The Way to Mastery of Lorem Ipsum<br />Or, How To Write and Publish a Book</title>
|
||||||
<author>Terran Publishing</author>
|
<author>Terran Publishing</author>
|
||||||
@@ -55,11 +56,11 @@ fun main() {
|
|||||||
|
|
||||||
<chapter>Writing Book using Computer</chapter>
|
<chapter>Writing Book using Computer</chapter>
|
||||||
|
|
||||||
<p>Writing book using a computer requires a use of the Book Typesetting Engine Extended, or <BTeX /></p>
|
<p>Writing book using a computer requires a use of the Book Typesetting Engine Extended, or <btex /></p>
|
||||||
|
|
||||||
<section>Full Control of the Shape</section>
|
<section>Full Control of the Shape</section>
|
||||||
|
|
||||||
<p>With <BTeX /> you can fully control how your publishing would look like, from a pile of papers that
|
<p>With <btex /> you can fully control how your publishing would look like, from a pile of papers that
|
||||||
look like they have been typed out using typewriter, a pile of papers but a fully-featured printouts that
|
look like they have been typed out using typewriter, a pile of papers but a fully-featured printouts that
|
||||||
have illustrations in it, to a fully-featured hardcover book.</p>
|
have illustrations in it, to a fully-featured hardcover book.</p>
|
||||||
|
|
||||||
@@ -70,31 +71,10 @@ fun main() {
|
|||||||
while Hardcover is considered bound and two pages are presented to the readers.</p>
|
while Hardcover is considered bound and two pages are presented to the readers.</p>
|
||||||
|
|
||||||
</manuscript>
|
</manuscript>
|
||||||
</btex>
|
</btexdoc>
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
val parser = SAXParserFactory.newDefaultInstance().newSAXParser()
|
val doku = BTeXParser(tex)
|
||||||
val stream: InputStream = ByteArrayInputStream(tex.encodeToByteArray())
|
|
||||||
val hb = object : DefaultHandler() {
|
|
||||||
override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) {
|
|
||||||
println(" $csiG$qName$csi0 ${(0 until attributes.length).map { "${attributes.getQName(it)}=${attributes.getValue(it)}" }}")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun endElement(uri: String, localName: String, qName: String) {
|
|
||||||
println("$csiG/$qName$csi0")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun characters(ch: CharArray, start: Int, length: Int) {
|
|
||||||
val str = String(ch.sliceArray(start until start+length)).replace('\n',' ').replace(Regex(" +"), " ").trim()
|
|
||||||
if (str.isNotBlank()) {
|
|
||||||
println("$str|")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
parser.parse(stream, hb)
|
|
||||||
}
|
}
|
||||||
@@ -713,7 +713,7 @@ internal object BlocksDrawer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var _tilesBufferAsTex: Texture = Texture(1, 1, Pixmap.Format.RGBA8888)
|
private var _tilesBufferAsTex: Texture = Texture(1, 1, Pixmap.Format.RGBA8888)
|
||||||
private val occlusionIntensity = 0.22222222f // too low value and dark-coloured walls won't darken enough
|
private val occlusionIntensity = 0.5f//0.22222222f // too low value and dark-coloured walls won't darken enough
|
||||||
|
|
||||||
private fun renderUsingBuffer(mode: Int, projectionMatrix: Matrix4, drawGlow: Boolean, drawEmissive: Boolean) {
|
private fun renderUsingBuffer(mode: Int, projectionMatrix: Matrix4, drawGlow: Boolean, drawEmissive: Boolean) {
|
||||||
//Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
|
//Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
|
||||||
|
|||||||
BIN
work_files/graphics/sprites/fixtures/musical_workbench.kra
LFS
Normal file
BIN
work_files/graphics/sprites/fixtures/musical_workbench.kra
LFS
Normal file
Binary file not shown.
Reference in New Issue
Block a user