From 76dd9a98e4cba6d46cffe5d85b91c20758933456 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Wed, 24 Apr 2024 01:13:46 +0900 Subject: [PATCH] btex stuffs --- assets/mods/basegame/books/btex.xml | 4 +- assets/mods/basegame/books/examination.xml | 4 +- .../sprites/fixtures/musical_workbench.tga | 3 + lib/TerrarumSansBitmap.jar | 4 +- src/net/torvald/btex/BTeXDocument.kt | 16 +- src/net/torvald/btex/BTeXParser.kt | 222 +++++++++++++---- src/net/torvald/terrarum/CreditSingleton.kt | 49 +++- src/net/torvald/terrarum/audio/AudioBank.kt | 4 + .../torvald/terrarum/audio/AudioProcessBuf.kt | 12 +- .../terrarum/modulebasegame/EntryPoint.kt | 4 + .../audio/audiobank/AudioBankMusicBox.kt | 3 +- .../modulebasegame/gameactors/Bachomatic.kt | 233 ++++++++++++++++++ .../gameactors/FixtureMechanicalTines.kt | 101 +------- .../gameactors/FixtureWorkbench.kt | 26 ++ .../modulebasegame/ui/UIMusicalWorkbench.kt | 62 +++++ src/net/torvald/terrarum/tests/BTeXTest.kt | 32 +-- .../terrarum/worlddrawer/BlocksDrawer.kt | 2 +- .../sprites/fixtures/musical_workbench.kra | 3 + 18 files changed, 602 insertions(+), 182 deletions(-) create mode 100644 assets/mods/basegame/sprites/fixtures/musical_workbench.tga create mode 100644 src/net/torvald/terrarum/modulebasegame/gameactors/Bachomatic.kt create mode 100644 src/net/torvald/terrarum/modulebasegame/ui/UIMusicalWorkbench.kt create mode 100644 work_files/graphics/sprites/fixtures/musical_workbench.kra diff --git a/assets/mods/basegame/books/btex.xml b/assets/mods/basegame/books/btex.xml index 484a5b8c2..8c7fc2ca1 100644 --- a/assets/mods/basegame/books/btex.xml +++ b/assets/mods/basegame/books/btex.xml @@ -1,4 +1,4 @@ - + The Way to Mastery of Lorem Ipsum<br />Or, How To Write and Publish a Book Terran Publishing @@ -46,4 +46,4 @@

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.

-
+ diff --git a/assets/mods/basegame/books/examination.xml b/assets/mods/basegame/books/examination.xml index 71e76202c..09c604ab7 100644 --- a/assets/mods/basegame/books/examination.xml +++ b/assets/mods/basegame/books/examination.xml @@ -1,4 +1,4 @@ - + @@ -54,4 +54,4 @@

Examination is a special format of the “book” that operates on the same book system.

-
+ diff --git a/assets/mods/basegame/sprites/fixtures/musical_workbench.tga b/assets/mods/basegame/sprites/fixtures/musical_workbench.tga new file mode 100644 index 000000000..a50a6adba --- /dev/null +++ b/assets/mods/basegame/sprites/fixtures/musical_workbench.tga @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57a5b26b256afdb01ceaf379ac51009f408966050d9154dae2fb383e5c9cea3c +size 4114 diff --git a/lib/TerrarumSansBitmap.jar b/lib/TerrarumSansBitmap.jar index b35bc7809..b2afa551b 100644 --- a/lib/TerrarumSansBitmap.jar +++ b/lib/TerrarumSansBitmap.jar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f2cde099f424df6512a35e6c3f629fdadeda552f57ae222b058739c75bcde90 -size 145003 +oid sha256:19cd63d57c4985d2e4f956b2516817941a72cfbf866111e1a2076f9a8ef81443 +size 188141 diff --git a/src/net/torvald/btex/BTeXDocument.kt b/src/net/torvald/btex/BTeXDocument.kt index c162d8ecd..c9f2c65c4 100644 --- a/src/net/torvald/btex/BTeXDocument.kt +++ b/src/net/torvald/btex/BTeXDocument.kt @@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.TextureRegion import net.torvald.terrarum.App import net.torvald.terrarum.ui.Toolkit +import net.torvald.terrarumsansbitmap.MovableType /** * Created by minjaesong on 2023-10-28. @@ -17,7 +18,9 @@ class BTeXDocument { var papersize = "standard" var pageWidth = 420 - var pageHeight = 25 * 24 + var lineHeight = 24 + var pageLines = 25 + var pageHeight = pageLines * lineHeight companion object { 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( val posX: Int, val posY: Int, val theme: String, val colour: Color, - val font: BitmapFont, - val text: String? = null, + val text: MovableTypeDrawCall? = null, val texture: TextureRegion? = null, ) { @@ -82,7 +90,7 @@ class BTeXDrawCall( batch.color = colour if (text != null && texture == null) { - font.draw(batch, text, px, py) + text.draw(batch, px, py) } else if (text == null && texture != null) { batch.draw(texture, px, py) diff --git a/src/net/torvald/btex/BTeXParser.kt b/src/net/torvald/btex/BTeXParser.kt index a72df9cb3..0c815efdb 100644 --- a/src/net/torvald/btex/BTeXParser.kt +++ b/src/net/torvald/btex/BTeXParser.kt @@ -4,13 +4,16 @@ import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.graphics.Color import net.torvald.terrarum.App import net.torvald.terrarum.btex.BTeXDocument -import net.torvald.terrarum.btex.BTeXDrawCall import net.torvald.terrarum.gameitems.ItemID import org.xml.sax.Attributes +import org.xml.sax.InputSource import org.xml.sax.helpers.DefaultHandler import java.io.* import java.util.* 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. @@ -27,18 +30,27 @@ object BTeXParser { 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 LINE_HEIGHT = 24 + private val LINE_HEIGHT = doc.lineHeight private var cover = "" private var inner = "" private var papersize = "" private var def = "" - private var pageWidth = 420 - private var pageLines = 25 - private var pageHeight = 25 * LINE_HEIGHT + private var btexOpened = false + + private var pageWidth = doc.pageWidth + private var pageLines = doc.pageLines + private var pageHeight = doc.pageHeight private val blockLut = HashMap() @@ -51,66 +63,93 @@ object BTeXParser { private var typeX = 0 private var typeY = 0 + private val elemOpeners: HashMap> = HashMap() + private val elemClosers: HashMap> = HashMap() + + init { + BTeXHandler::class.declaredFunctions.filter { it.findAnnotation() != null }.forEach { + println("Tag opener: ${it.name}") + elemOpeners[it.name] = it + } + + BTeXHandler::class.declaredFunctions.filter { it.findAnnotation() != 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 = 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) { - 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) val attribs = HashMap().also { 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) { - "btex" -> { - if (attribs.containsKey("def")) - def = attribs["def"]!! - else { - cover = attribs["cover"] ?: "printout" - inner = attribs["inner"] ?: "standard" - papersize = attribs["papersize"] ?: "standard" - - pageWidth = pageWidthMap[papersize]!! - pageLines = pageHeightMap[papersize]!! - pageHeight = pageLines * LINE_HEIGHT - - doc.pageWidth = pageWidth - doc.pageHeight = pageHeight + elemOpeners["processElem$theTag"].let { + if (it == null) + System.err.println("Unknown tag: $theTag") + else { + try { + it.call(this, this, doc, theTag, uri, attribs) + } + catch (e: Throwable) { + throw BTeXParsingException(e.stackTraceToString()) } } - "pair" -> { - if (tagStack.size == 3 && mode == "blocklut") { - blockLut[attribs["key"]!!] = attribs["value"]!! - } - else { - throw BTeXParsingException(" used outside of ") - } - } - "span" -> { - attribs["span"]?.let { - spanColour = it - } - } - } + +// printdbg("Start element \t($tag)") } override fun endElement(uri: String, localName: String, qName: String) { - tagStack.removeLast() + val popped = tagStack.removeLast() - when (qName) { - "span" -> { - spanColour = null + val theTag = qName.uppercase() + + 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) { - val str = String(ch.sliceArray(start until start+length)).replace('\n',' ').replace(Regex(" +"), " ").trim() - val font = getFont() - advanceCursorPre(font.getWidth(str), 0) - doc.appendDrawCall(BTeXDrawCall(typeX, typeY, inner, getSpanColour(), font, str)) - advanceCursorPost(font.getWidth(str), 0) + val str = + String(ch.sliceArray(start until start + length)).replace('\n', ' ').replace(Regex(" +"), " ")//.trim() + + if (str.isNotBlank()) { + printdbg("Characters \t\"$str\"") + } } private fun advanceCursorPre(w: Int, h: Int) { @@ -149,8 +188,99 @@ object BTeXParser { private val pageHeightMap = hashMapOf( "standard" to 25 ) + + + @OpenTag // reflective access is impossible with 'private' + fun processElemBTEXDOC(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap) { + 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) { + if (tagStack.size == 3 && tagStack.getOrNull(1) == "blocklut") { + blockLut[attribs["key"]!!] = attribs["value"]!! + } + else { + throw BTeXParsingException(" used outside of ") + } + } + + @OpenTag // reflective access is impossible with 'private' + fun processElemSPAN(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap) { + attribs["span"]?.let { + spanColour = it + } + } + + @OpenTag // reflective access is impossible with 'private' + fun processElemTABLEOFCONTENTS(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap) { + // 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) { + + } + + @OpenTag // reflective access is impossible with 'private' + fun processElemNEWPAGE(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap) { + + } + + @OpenTag // reflective access is impossible with 'private' + fun processElemP(handler: BTeXHandler, doc: BTeXDocument, theTag: String, uri: String, attribs: HashMap) { + + } + + @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) { + + } + + + + @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 + } diff --git a/src/net/torvald/terrarum/CreditSingleton.kt b/src/net/torvald/terrarum/CreditSingleton.kt index 647f3ebed..f828b4d7a 100644 --- a/src/net/torvald/terrarum/CreditSingleton.kt +++ b/src/net/torvald/terrarum/CreditSingleton.kt @@ -37,7 +37,7 @@ along with this program. If not, see . $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 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. +$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 @@ -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 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 GraalVM Community Edition consists of multiple modules. The software as a whole, diff --git a/src/net/torvald/terrarum/audio/AudioBank.kt b/src/net/torvald/terrarum/audio/AudioBank.kt index 93a025c24..f269c4487 100644 --- a/src/net/torvald/terrarum/audio/AudioBank.kt +++ b/src/net/torvald/terrarum/audio/AudioBank.kt @@ -7,6 +7,10 @@ import com.badlogic.gdx.utils.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 protected val hash = System.nanoTime() diff --git a/src/net/torvald/terrarum/audio/AudioProcessBuf.kt b/src/net/torvald/terrarum/audio/AudioProcessBuf.kt index c16192cdd..e61b4bb31 100644 --- a/src/net/torvald/terrarum/audio/AudioProcessBuf.kt +++ b/src/net/torvald/terrarum/audio/AudioProcessBuf.kt @@ -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 Lcache = HashMap(1048576) +// private val Lcache = HashMap(1048576) 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) 1.0 else if (-TAPS <= x && x < TAPS) (TAPS * sin(PI * x) * sin(PI * x / TAPS)) / (PI * PI * x * x) else 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 diff --git a/src/net/torvald/terrarum/modulebasegame/EntryPoint.kt b/src/net/torvald/terrarum/modulebasegame/EntryPoint.kt index 89324e50b..7bb7be72e 100644 --- a/src/net/torvald/terrarum/modulebasegame/EntryPoint.kt +++ b/src/net/torvald/terrarum/modulebasegame/EntryPoint.kt @@ -2,6 +2,7 @@ package net.torvald.terrarum.modulebasegame import net.torvald.terrarum.* 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.weather.WeatherMixer @@ -42,6 +43,9 @@ class EntryPoint : ModuleEntryPoint() { WeatherCodex.weatherById["titlescreen"] = 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) { println("[EntryPoint] Crafting Recipes: ") diff --git a/src/net/torvald/terrarum/modulebasegame/audio/audiobank/AudioBankMusicBox.kt b/src/net/torvald/terrarum/modulebasegame/audio/audiobank/AudioBankMusicBox.kt index b9a94cc19..005b35df1 100644 --- a/src/net/torvald/terrarum/modulebasegame/audio/audiobank/AudioBankMusicBox.kt +++ b/src/net/torvald/terrarum/modulebasegame/audio/audiobank/AudioBankMusicBox.kt @@ -76,7 +76,8 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {}) bufferR.fill(0f) // 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 it.notes.forEach { note -> val noteSamples = getSample(note) diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/Bachomatic.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/Bachomatic.kt new file mode 100644 index 000000000..a385c79bf --- /dev/null +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/Bachomatic.kt @@ -0,0 +1,233 @@ +package net.torvald.terrarum.modulebasegame.gameactors + +/** + * Created by minjaesong on 2024-04-18. + */ +interface Bachomatic { + + operator fun invoke(): List + +} + +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 { + 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 { + 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 { + 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 { + return ns.map { 1L shl it } // arpeggiate + } + + fun toPianoRoll(vararg noteAndLen: Pair): List { + val ret = MutableList(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(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 + + + +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMechanicalTines.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMechanicalTines.kt index 0c5877dd9..aa84df81d 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMechanicalTines.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMechanicalTines.kt @@ -1,15 +1,12 @@ package net.torvald.terrarum.modulebasegame.gameactors -import com.badlogic.gdx.graphics.Color import com.jme3.math.FastMath import com.jme3.math.FastMath.DEG_TO_RAD -import net.torvald.colourutil.HUSLColorConverter import net.torvald.colourutil.OKHsv import net.torvald.colourutil.toColor import net.torvald.colourutil.tosRGB import net.torvald.random.HQRNG import net.torvald.terrarum.App -import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.CommonResourcePool import net.torvald.terrarum.INGAME 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.terrarumsansbitmap.gdx.TextureRegionPack import org.dyn4j.geometry.Vector2 -import kotlin.math.pow /** * Created by minjaesong on 2024-04-15. @@ -92,99 +88,18 @@ class FixtureMechanicalTines : Electric { } - - private fun findSetBits(num: Long): List { - val result = mutableListOf() - for (i in 0 until 61) { - if (num and (1L shl i) != 0L) { - result.add(i) - } - } - return result - } - companion object { - @Transient private val TICK_DIVISOR = 10 + @Transient val testNotes = PreludeInCshMaj() - @Transient val testNotes = 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 { - 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 { - 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 { - 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 { - return ns.map { 1L shl it } // arpeggiate - } - - private fun toPianoRoll(vararg noteAndLen: Pair): List { - val ret = MutableList(noteAndLen.sumOf { it.second }) { 0 } - var c = 0 - noteAndLen.forEach { (note, len) -> - ret[c] = note - c += len + fun findSetBits(num: Long): List { + val result = mutableListOf() + for (i in 0 until 61) { + if (num and (1L shl i) != 0L) { + result.add(i) + } } - return ret + return result } - - private fun toPianoRoll(vararg notes: Long) = List(notes.size * TICK_DIVISOR) { - if (it % TICK_DIVISOR == 0) notes[it / TICK_DIVISOR] else 0 - } - } } diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureWorkbench.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureWorkbench.kt index 62eef3b7d..bceeaf91e 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureWorkbench.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureWorkbench.kt @@ -7,6 +7,7 @@ import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase import net.torvald.terrarum.modulebasegame.ui.UICrafting import net.torvald.terrarum.modulebasegame.ui.UIEngravingTextSign +import net.torvald.terrarum.modulebasegame.ui.UIMusicalWorkbench import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack /** @@ -85,4 +86,29 @@ class FixtureEngravingWorkbench : FixtureBase, CraftingStation { actorValue[AVKey.BASEMASS] = 40.0 } +} + +/** + * 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 + } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UIMusicalWorkbench.kt b/src/net/torvald/terrarum/modulebasegame/ui/UIMusicalWorkbench.kt new file mode 100644 index 000000000..7d1c92688 --- /dev/null +++ b/src/net/torvald/terrarum/modulebasegame/ui/UIMusicalWorkbench.kt @@ -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 { + val ret = MutableList(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() + 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") + } + + +} + diff --git a/src/net/torvald/terrarum/tests/BTeXTest.kt b/src/net/torvald/terrarum/tests/BTeXTest.kt index b20061c3d..0797c6b6a 100644 --- a/src/net/torvald/terrarum/tests/BTeXTest.kt +++ b/src/net/torvald/terrarum/tests/BTeXTest.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum.tests +import net.torvald.btex.BTeXParser import org.xml.sax.Attributes import org.xml.sax.HandlerBase import org.xml.sax.helpers.DefaultHandler @@ -16,7 +17,7 @@ fun main() { val csiG = "\u001B[32m" val csi0 = "\u001B[m" - val tex = """ + val tex = """ The Way to Mastery of Lorem Ipsum<br />Or, How To Write and Publish a Book Terran Publishing @@ -55,11 +56,11 @@ fun main() { Writing Book using Computer -

Writing book using a computer requires a use of the Book Typesetting Engine Extended, or

+

Writing book using a computer requires a use of the Book Typesetting Engine Extended, or

Full Control of the Shape
-

With you can fully control how your publishing would look like, from a pile of papers that +

With 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 have illustrations in it, to a fully-featured hardcover book.

@@ -70,31 +71,10 @@ fun main() { while Hardcover is considered bound and two pages are presented to the readers.

-
+ """ - val parser = SAXParserFactory.newDefaultInstance().newSAXParser() - 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) + val doku = BTeXParser(tex) } \ No newline at end of file diff --git a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt index f65295b5b..f6fb35111 100644 --- a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt +++ b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt @@ -713,7 +713,7 @@ internal object BlocksDrawer { } 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) { //Gdx.gl.glClearColor(.094f, .094f, .094f, 0f) diff --git a/work_files/graphics/sprites/fixtures/musical_workbench.kra b/work_files/graphics/sprites/fixtures/musical_workbench.kra new file mode 100644 index 000000000..8f39ec5e1 --- /dev/null +++ b/work_files/graphics/sprites/fixtures/musical_workbench.kra @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08f760eb27e32585471bb32bbefb89e1432344f1f10716f58b20401457723fe9 +size 109056