mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 08:38:30 +09:00
Compare commits
70 Commits
v0.3.2
...
v0.3.3-tes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1e45f1743 | ||
|
|
8dda7ac79b | ||
|
|
74b8cc20b7 | ||
|
|
f75a7dd812 | ||
|
|
b2454e4ca2 | ||
|
|
45af955488 | ||
|
|
1f39b9d448 | ||
|
|
26a4cdbce1 | ||
|
|
bf87dc04cb | ||
|
|
8535b0ce13 | ||
|
|
6e0004f165 | ||
|
|
845333f33d | ||
|
|
6988feb731 | ||
|
|
ac2c7b1148 | ||
|
|
d6145fd0da | ||
|
|
194089827c | ||
|
|
d69d032f74 | ||
|
|
a9dbea3d16 | ||
|
|
52938a4b60 | ||
|
|
a21f986f30 | ||
|
|
547158a313 | ||
|
|
0a8b5f33f4 | ||
|
|
da8d620766 | ||
|
|
7dd520393c | ||
|
|
dc83e12170 | ||
|
|
d6b2940d8f | ||
|
|
c5dfe46b76 | ||
|
|
3d3926c08b | ||
|
|
9a90bf69d4 | ||
|
|
0ed5472d8a | ||
|
|
97a7a36030 | ||
|
|
662069466a | ||
|
|
52cff00338 | ||
|
|
1a40334f8e | ||
|
|
763f512419 | ||
|
|
620a1c6956 | ||
|
|
5f4fcdba69 | ||
|
|
7a79f444b2 | ||
|
|
e4b947ce69 | ||
|
|
fdfec960ca | ||
|
|
75021ecfa2 | ||
|
|
c90ef21bfa | ||
|
|
3fce5d7e95 | ||
|
|
8db1228e70 | ||
|
|
5f7f724058 | ||
|
|
fab4179068 | ||
|
|
32803b6f18 | ||
|
|
f8f75fb7b6 | ||
|
|
9919a99032 | ||
|
|
6a43d1a5bd | ||
|
|
24c971e4b8 | ||
|
|
62f0fd7c68 | ||
|
|
3dec312989 | ||
|
|
77b51a45dd | ||
|
|
d1b4ce3404 | ||
|
|
fd7b88307c | ||
|
|
579b6b5b29 | ||
|
|
cef58f6a73 | ||
|
|
c0c98c3b80 | ||
|
|
88d844cc09 | ||
|
|
2411db17a7 | ||
|
|
53d372be38 | ||
|
|
88831051c8 | ||
|
|
87d92ecb74 | ||
|
|
6672dffdbc | ||
|
|
cd00ab4c7f | ||
|
|
014306c209 | ||
|
|
30fb57eca3 | ||
|
|
52ad8f0c46 | ||
|
|
1b08039018 |
@@ -1,26 +1,17 @@
|
|||||||
package net.torvald.terrarum.modulecomputers.gameactors
|
package net.torvald.terrarum.modulecomputers.gameactors
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
|
||||||
import com.badlogic.gdx.Input
|
|
||||||
import com.badlogic.gdx.graphics.*
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|
||||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
import kotlin.coroutines.*
|
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
import net.torvald.terrarum.langpack.Lang
|
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.BlockBox
|
import net.torvald.terrarum.modulebasegame.gameactors.BlockBox
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
|
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.modulecomputers.ui.UIHomeComputer
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
|
||||||
import net.torvald.tsvm.*
|
import net.torvald.tsvm.*
|
||||||
import net.torvald.tsvm.peripheral.AdapterConfig
|
import net.torvald.tsvm.peripheral.AdapterConfig
|
||||||
import net.torvald.tsvm.peripheral.GraphicsAdapter
|
import net.torvald.tsvm.peripheral.GraphicsAdapter
|
||||||
import net.torvald.tsvm.peripheral.VMProgramRom
|
import net.torvald.tsvm.peripheral.VMProgramRom
|
||||||
import net.torvald.unicode.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2021-12-04.
|
* Created by minjaesong on 2021-12-04.
|
||||||
@@ -131,77 +122,3 @@ class FixtureHomeComputer : FixtureBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class UIHomeComputer : UICanvas(
|
|
||||||
toggleKeyLiteral = Input.Keys.ESCAPE, // FIXME why do I have specify ESC for it to function? ESC should be work as the default key
|
|
||||||
toggleButtonLiteral = App.getConfigInt("control_gamepad_start"),
|
|
||||||
) {
|
|
||||||
override var width = 640
|
|
||||||
override var height = 480
|
|
||||||
override var openCloseTime = 0f
|
|
||||||
|
|
||||||
private val drawOffX = (width - 560).div(2).toFloat()
|
|
||||||
private val drawOffY = (height - 448).div(2).toFloat()
|
|
||||||
|
|
||||||
private var batch: FlippingSpriteBatch
|
|
||||||
private var camera: OrthographicCamera
|
|
||||||
|
|
||||||
internal lateinit var vm: VM
|
|
||||||
internal lateinit var fixture: FixtureHomeComputer
|
|
||||||
|
|
||||||
init {
|
|
||||||
batch = FlippingSpriteBatch()
|
|
||||||
camera = OrthographicCamera(width.toFloat(), height.toFloat())
|
|
||||||
//val m = Matrix4()
|
|
||||||
//m.setToOrtho2D(0f, 0f, width.toFloat(), height.toFloat())
|
|
||||||
batch.projectionMatrix = camera.combined
|
|
||||||
}
|
|
||||||
|
|
||||||
private val fbo = FrameBuffer(Pixmap.Format.RGBA8888, width, height, false)
|
|
||||||
|
|
||||||
private val controlHelp =
|
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}\u3000 " +
|
|
||||||
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_T$KEYCAP_R Terminate\u3000" +
|
|
||||||
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_R$KEYCAP_S Reset\u3000" +
|
|
||||||
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_R$KEYCAP_Q SysRq"
|
|
||||||
|
|
||||||
override fun updateUI(delta: Float) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun renderUI(otherBatch: SpriteBatch, otherCamera: Camera) {
|
|
||||||
otherBatch.end()
|
|
||||||
|
|
||||||
fbo.inAction(camera, batch) {
|
|
||||||
Gdx.gl.glClearColor(0f,0f,0f,1f)
|
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) // to hide the crap might be there
|
|
||||||
|
|
||||||
(vm.peripheralTable[1].peripheral as? GraphicsAdapter)?.let { gpu ->
|
|
||||||
val clearCol = gpu.getBackgroundColour()
|
|
||||||
Gdx.gl.glClearColor(clearCol.r, clearCol.g, clearCol.b, clearCol.a)
|
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
|
||||||
|
|
||||||
gpu.render(Gdx.graphics.deltaTime, batch, drawOffX, drawOffY, true, fbo) // gpu.render will internally end() the fbo then begin() again before using the batch I've fed in
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
otherBatch.begin()
|
|
||||||
otherBatch.shader = null
|
|
||||||
blendNormalStraightAlpha(otherBatch)
|
|
||||||
otherBatch.color = Color.WHITE
|
|
||||||
otherBatch.draw(fbo.colorBufferTexture, posX.toFloat(), posY.toFloat(), width.toFloat(), height.toFloat())
|
|
||||||
otherBatch.color = Toolkit.Theme.COL_INACTIVE
|
|
||||||
Toolkit.drawBoxBorder(otherBatch, posX - 1, posY - 1, width + 2, height + 2)
|
|
||||||
|
|
||||||
App.fontGame.draw(otherBatch, controlHelp, posX, posY + height + 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun doOpening(delta: Float) {
|
|
||||||
super.doOpening(delta)
|
|
||||||
fixture.startVM()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
fbo.dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package net.torvald.terrarum.modulecomputers.ui
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.Input
|
||||||
|
import com.badlogic.gdx.graphics.*
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||||
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.langpack.Lang
|
||||||
|
import net.torvald.terrarum.modulecomputers.gameactors.FixtureHomeComputer
|
||||||
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
|
import net.torvald.tsvm.VM
|
||||||
|
import net.torvald.tsvm.peripheral.GraphicsAdapter
|
||||||
|
import net.torvald.unicode.*
|
||||||
|
|
||||||
|
internal class UIHomeComputer : UICanvas(
|
||||||
|
toggleKeyLiteral = null,
|
||||||
|
toggleButtonLiteral = "control_gamepad_start",
|
||||||
|
) {
|
||||||
|
override var width = 640
|
||||||
|
override var height = 480
|
||||||
|
override var openCloseTime = 0f
|
||||||
|
|
||||||
|
private val drawOffX = (width - 560).div(2).toFloat()
|
||||||
|
private val drawOffY = (height - 448).div(2).toFloat()
|
||||||
|
|
||||||
|
private var batch: FlippingSpriteBatch
|
||||||
|
private var camera: OrthographicCamera
|
||||||
|
|
||||||
|
internal lateinit var vm: VM
|
||||||
|
internal lateinit var fixture: FixtureHomeComputer
|
||||||
|
|
||||||
|
init {
|
||||||
|
batch = FlippingSpriteBatch()
|
||||||
|
camera = OrthographicCamera(width.toFloat(), height.toFloat())
|
||||||
|
//val m = Matrix4()
|
||||||
|
//m.setToOrtho2D(0f, 0f, width.toFloat(), height.toFloat())
|
||||||
|
batch.projectionMatrix = camera.combined
|
||||||
|
}
|
||||||
|
|
||||||
|
private val fbo = FrameBuffer(Pixmap.Format.RGBA8888, width, height, false)
|
||||||
|
|
||||||
|
private val controlHelp =
|
||||||
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}\u3000 " +
|
||||||
|
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_T$KEYCAP_R Terminate\u3000" +
|
||||||
|
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_R$KEYCAP_S Reset\u3000" +
|
||||||
|
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_R$KEYCAP_Q SysRq"
|
||||||
|
|
||||||
|
override fun updateUI(delta: Float) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renderUI(otherBatch: SpriteBatch, otherCamera: Camera) {
|
||||||
|
otherBatch.end()
|
||||||
|
|
||||||
|
fbo.inAction(camera, batch) {
|
||||||
|
Gdx.gl.glClearColor(0f,0f,0f,1f)
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) // to hide the crap might be there
|
||||||
|
|
||||||
|
(vm.peripheralTable[1].peripheral as? GraphicsAdapter)?.let { gpu ->
|
||||||
|
val clearCol = gpu.getBackgroundColour()
|
||||||
|
Gdx.gl.glClearColor(clearCol.r, clearCol.g, clearCol.b, clearCol.a)
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||||
|
|
||||||
|
gpu.render(Gdx.graphics.deltaTime, batch, drawOffX, drawOffY, true, fbo) // gpu.render will internally end() the fbo then begin() again before using the batch I've fed in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
otherBatch.begin()
|
||||||
|
otherBatch.shader = null
|
||||||
|
blendNormalStraightAlpha(otherBatch)
|
||||||
|
otherBatch.color = Color.WHITE
|
||||||
|
otherBatch.draw(fbo.colorBufferTexture, posX.toFloat(), posY.toFloat(), width.toFloat(), height.toFloat())
|
||||||
|
otherBatch.color = Toolkit.Theme.COL_INACTIVE
|
||||||
|
Toolkit.drawBoxBorder(otherBatch, posX - 1, posY - 1, width + 2, height + 2)
|
||||||
|
|
||||||
|
App.fontGame.draw(otherBatch, controlHelp, posX, posY + height + 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doOpening(delta: Float) {
|
||||||
|
super.doOpening(delta)
|
||||||
|
fixture.startVM()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
fbo.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
BIN
assets/clut/skybox.png
LFS
BIN
assets/clut/skybox.png
LFS
Binary file not shown.
@@ -8,6 +8,7 @@
|
|||||||
"GAME_ACTION_MOVE_VERB" : "Move",
|
"GAME_ACTION_MOVE_VERB" : "Move",
|
||||||
"GAME_ACTION_ZOOM" : "Zoom",
|
"GAME_ACTION_ZOOM" : "Zoom",
|
||||||
"MENU_IO_AUTOSAVE": "Autosave",
|
"MENU_IO_AUTOSAVE": "Autosave",
|
||||||
|
"MENU_IO_CLEAR": "Clear",
|
||||||
"MENU_IO_IMPORT": "Import",
|
"MENU_IO_IMPORT": "Import",
|
||||||
"MENU_IO_MANUAL_SAVE": "Manual Save",
|
"MENU_IO_MANUAL_SAVE": "Manual Save",
|
||||||
"MENU_LABEL_COPYRIGHT": "Copyright",
|
"MENU_LABEL_COPYRIGHT": "Copyright",
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
"MENU_LABEL_IME": "IME",
|
"MENU_LABEL_IME": "IME",
|
||||||
"MENU_LABEL_IME_TOGGLE": "Toggle IME",
|
"MENU_LABEL_IME_TOGGLE": "Toggle IME",
|
||||||
"MENU_LABEL_KEYBOARD_LAYOUT": "Keyboard Layout",
|
"MENU_LABEL_KEYBOARD_LAYOUT": "Keyboard Layout",
|
||||||
|
"MENU_LABEL_PASTE": "Paste",
|
||||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "Paste from Clipboard",
|
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "Paste from Clipboard",
|
||||||
"MENU_LABEL_PRESS_START_SYMBOL": "Press >",
|
"MENU_LABEL_PRESS_START_SYMBOL": "Press >",
|
||||||
"MENU_LABEL_RESET" : "Reset",
|
"MENU_LABEL_RESET" : "Reset",
|
||||||
@@ -23,6 +25,7 @@
|
|||||||
"MENU_LABEL_STREAMING": "Livestreaming",
|
"MENU_LABEL_STREAMING": "Livestreaming",
|
||||||
"MENU_LABEL_SYSTEM_INFO": "System Info",
|
"MENU_LABEL_SYSTEM_INFO": "System Info",
|
||||||
"MENU_MODULES" : "Modules",
|
"MENU_MODULES" : "Modules",
|
||||||
|
"MENU_OPTIONS_ATLAS_TEXTURE_SIZE": "Atlas Texture Size",
|
||||||
"MENU_OPTIONS_AUTOSAVE": "Autosave",
|
"MENU_OPTIONS_AUTOSAVE": "Autosave",
|
||||||
"MENU_OPTIONS_BLUR": "Blur",
|
"MENU_OPTIONS_BLUR": "Blur",
|
||||||
"MENU_OPTIONS_DEBUG_CONSOLE": "Debug Console",
|
"MENU_OPTIONS_DEBUG_CONSOLE": "Debug Console",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"GAME_ACTION_MOVE_VERB" : "이동하기",
|
"GAME_ACTION_MOVE_VERB" : "이동하기",
|
||||||
"GAME_ACTION_ZOOM" : "확대·축소",
|
"GAME_ACTION_ZOOM" : "확대·축소",
|
||||||
"MENU_IO_AUTOSAVE": "자동 저장",
|
"MENU_IO_AUTOSAVE": "자동 저장",
|
||||||
|
"MENU_IO_CLEAR": "지우기",
|
||||||
"MENU_IO_IMPORT": "가져오기",
|
"MENU_IO_IMPORT": "가져오기",
|
||||||
"MENU_IO_MANUAL_SAVE": "수동 저장",
|
"MENU_IO_MANUAL_SAVE": "수동 저장",
|
||||||
"MENU_LABEL_COPYRIGHT": "저작권",
|
"MENU_LABEL_COPYRIGHT": "저작권",
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
"MENU_LABEL_IME": "입력기",
|
"MENU_LABEL_IME": "입력기",
|
||||||
"MENU_LABEL_IME_TOGGLE": "입력기 켜고 끄기",
|
"MENU_LABEL_IME_TOGGLE": "입력기 켜고 끄기",
|
||||||
"MENU_LABEL_KEYBOARD_LAYOUT": "자판 배열",
|
"MENU_LABEL_KEYBOARD_LAYOUT": "자판 배열",
|
||||||
|
"MENU_LABEL_PASTE": "붙여넣기",
|
||||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "복사한 텍스트 붙여넣기",
|
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "복사한 텍스트 붙여넣기",
|
||||||
"MENU_LABEL_PRESS_START_SYMBOL": ">을 누르세요",
|
"MENU_LABEL_PRESS_START_SYMBOL": ">을 누르세요",
|
||||||
"MENU_LABEL_RESET" : "재설정",
|
"MENU_LABEL_RESET" : "재설정",
|
||||||
@@ -23,6 +25,7 @@
|
|||||||
"MENU_LABEL_STREAMING": "실시간 방송",
|
"MENU_LABEL_STREAMING": "실시간 방송",
|
||||||
"MENU_LABEL_SYSTEM_INFO": "시스템 정보",
|
"MENU_LABEL_SYSTEM_INFO": "시스템 정보",
|
||||||
"MENU_MODULES" : "모듈",
|
"MENU_MODULES" : "모듈",
|
||||||
|
"MENU_OPTIONS_ATLAS_TEXTURE_SIZE": "아틀라스 텍스처 크기",
|
||||||
"MENU_OPTIONS_AUTOSAVE": "자동 저장",
|
"MENU_OPTIONS_AUTOSAVE": "자동 저장",
|
||||||
"MENU_OPTIONS_BLUR": "흐림",
|
"MENU_OPTIONS_BLUR": "흐림",
|
||||||
"MENU_OPTIONS_DEBUG_CONSOLE": "디버그 콘솔",
|
"MENU_OPTIONS_DEBUG_CONSOLE": "디버그 콘솔",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
"id";"drop";"spawn";"name";"shdr";"shdg";"shdb";"shduv";"str";"dsty";"mate";"solid";"wall";"grav";"dlfn";"fv";"fr";"lumr";"lumg";"lumb";"lumuv";"colour";"vscs";"refl";"tags"
|
"id";"drop";"spawn";"name";"shdr";"shdg";"shdb";"shduv";"str";"dsty";"mate";"solid";"wall";"grav";"dlfn";"fv";"fr";"lumr";"lumg";"lumb";"lumuv";"colour";"vscs";"refl";"tags"
|
||||||
"0";"0";"0";"BLOCK_AIR";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";""
|
"0";"0";"0";"BLOCK_AIR";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INCONSEQUENTIAL"
|
||||||
"16";"17";"17";"BLOCK_STONE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURAL"
|
"16";"17";"17";"BLOCK_STONE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURAL"
|
||||||
"17";"17";"17";"BLOCK_STONE_QUARRIED";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK"
|
"17";"17";"17";"BLOCK_STONE_QUARRIED";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK"
|
||||||
"18";"18";"18";"BLOCK_STONE_TILE_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.18";"STONE"
|
"18";"18";"18";"BLOCK_STONE_TILE_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.18";"STONE"
|
||||||
@@ -188,6 +188,7 @@
|
|||||||
## Some tags are reserved for internal use, which are:
|
## Some tags are reserved for internal use, which are:
|
||||||
## - INTERNAL: denotes that the tile is internal-use. Will not be rendered unless debug window is on.
|
## - INTERNAL: denotes that the tile is internal-use. Will not be rendered unless debug window is on.
|
||||||
## - DORENDER: this internal tile must go through the standard-issue tile drawing routine.
|
## - DORENDER: this internal tile must go through the standard-issue tile drawing routine.
|
||||||
|
## - INCONSEQUENTIAL: denotes that this tile can be overwritten without dropping it. Usually used with flower tiles.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
## References ##
|
## References ##
|
||||||
|
|||||||
|
Can't render this file because it contains an unexpected character in line 179 and column 37.
|
@@ -32,4 +32,5 @@ Teleport
|
|||||||
ToggleNoClip
|
ToggleNoClip
|
||||||
Zoom
|
Zoom
|
||||||
DynToStatic
|
DynToStatic
|
||||||
DebugFillInventory
|
DebugFillInventory
|
||||||
|
Uuid
|
||||||
|
@@ -8,6 +8,7 @@ id;classname
|
|||||||
8;net.torvald.terrarum.modulebasegame.gameitems.ItemLogicSignalEmitter
|
8;net.torvald.terrarum.modulebasegame.gameitems.ItemLogicSignalEmitter
|
||||||
9;net.torvald.terrarum.modulebasegame.gameitems.WireCutterAll
|
9;net.torvald.terrarum.modulebasegame.gameitems.WireCutterAll
|
||||||
10;net.torvald.terrarum.modulebasegame.gameitems.ItemTypewriter
|
10;net.torvald.terrarum.modulebasegame.gameitems.ItemTypewriter
|
||||||
|
11;net.torvald.terrarum.modulebasegame.gameitems.ItemWallCalendar
|
||||||
|
|
||||||
256;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorOak
|
256;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorOak
|
||||||
257;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorEbony
|
257;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorEbony
|
||||||
|
|||||||
|
34
assets/mods/basegame/locales/en/calendar.json
Normal file
34
assets/mods/basegame/locales/en/calendar.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"MENU_CALENDAR_CALENDAR": "Calendar",
|
||||||
|
"MENU_CALENDAR_EVENTS": "Events",
|
||||||
|
"MENU_CALENDAR_ADD_NEW_EVENT": "Add New Event",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_SPRING": "Spring",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_SUMMER": "Summer",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_AUTUMN": "Autumn",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_WINTER": "Winter",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_SPRI": "Spri",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_SUMM": "Summ",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_AUTM": "Autm",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_WINT": "Wint",
|
||||||
|
"CONTEXT_CALENDAR_DATE_FORMAT_Y": "Year {0}",
|
||||||
|
"CONTEXT_CALENDAR_DATE_FORMAT_YMD": "Year {0} {1} {2}",
|
||||||
|
"CONTEXT_CALENDAR_DATE_FORMAT_YMD_DDD": "Year {0} {1} {2} {3}",
|
||||||
|
|
||||||
|
"CONTEXT_CALENDAR_DAY_MONDAG_DNT": "Mondag",
|
||||||
|
"CONTEXT_CALENDAR_DAY_TYSDAG_DNT": "Tysdag",
|
||||||
|
"CONTEXT_CALENDAR_DAY_MIDTVEKE_DNT": "Midtveke",
|
||||||
|
"CONTEXT_CALENDAR_DAY_TORSDAG_DNT": "Torsdag",
|
||||||
|
"CONTEXT_CALENDAR_DAY_FREDAG_DNT": "Fredag",
|
||||||
|
"CONTEXT_CALENDAR_DAY_LAURDAG_DNT": "Laurdag",
|
||||||
|
"CONTEXT_CALENDAR_DAY_SUNDAG_DNT": "Sundag",
|
||||||
|
"CONTEXT_CALENDAR_DAY_VERDDAG_DNT": "Verddag",
|
||||||
|
"CONTEXT_CALENDAR_DAY_MON_DNT": "Mon",
|
||||||
|
"CONTEXT_CALENDAR_DAY_TYS_DNT": "Tys",
|
||||||
|
"CONTEXT_CALENDAR_DAY_MID_DNT": "Mid",
|
||||||
|
"CONTEXT_CALENDAR_DAY_TOR_DNT": "Tor",
|
||||||
|
"CONTEXT_CALENDAR_DAY_FRE_DNT": "Fre",
|
||||||
|
"CONTEXT_CALENDAR_DAY_LAU_DNT": "Lau",
|
||||||
|
"CONTEXT_CALENDAR_DAY_SUN_DNT": "Sun",
|
||||||
|
"CONTEXT_CALENDAR_DAY_VER_DNT": "Ver",
|
||||||
|
"CONTEXT_CALENDAR_DATE_FORMAT_YMD_SHORT_DNT": "ɣ{0}-{1}-{2}"
|
||||||
|
}
|
||||||
@@ -1,23 +1,24 @@
|
|||||||
{
|
{
|
||||||
|
"CONTEXT_GENERATOR_SEED": "Seed",
|
||||||
|
"CONTEXT_ITEM_MAP": "Map",
|
||||||
|
"CONTEXT_ITEM_TOOL_PLURAL": "Tools",
|
||||||
|
"CONTEXT_PLACE_COORDINATE": "Coordinate",
|
||||||
|
"CONTEXT_WORLD_COUNT": "Worlds: ",
|
||||||
"CONTEXT_WORLD_NEW": "New World",
|
"CONTEXT_WORLD_NEW": "New World",
|
||||||
"MENU_LABEL_DELETE_WORLD": "Delete World",
|
"MENU_LABEL_DELETE_WORLD": "Delete World",
|
||||||
"CONTEXT_WORLD_COUNT": "Worlds: ",
|
|
||||||
"GAME_INVENTORY_INGREDIENTS": "Ingredients",
|
|
||||||
"GAME_INVENTORY_POTIONS": "Potions",
|
|
||||||
"GAME_INVENTORY_BLOCKS": "Blocks",
|
|
||||||
"GAME_INVENTORY_WALLS": "Walls",
|
|
||||||
"CONTEXT_ITEM_TOOL_PLURAL": "Tools",
|
|
||||||
"GAME_INVENTORY_FAVORITES": "Favorites",
|
|
||||||
"GAME_INVENTORY_REGISTER": "Register",
|
|
||||||
"CONTEXT_ITEM_MAP": "Map",
|
|
||||||
"MENU_LABEL_MENU": "Menu",
|
"MENU_LABEL_MENU": "Menu",
|
||||||
"CONTEXT_GENERATOR_SEED": "Seed",
|
"MENU_LABEL_PREV_SAVES": "Previous Saves",
|
||||||
|
"MENU_LABEL_RENAME": "Rename",
|
||||||
|
"GAME_ACTION_CRAFT": "Craft",
|
||||||
"GAME_ACTION_GRAPPLE": "Grapple",
|
"GAME_ACTION_GRAPPLE": "Grapple",
|
||||||
"GAME_ACTION_QUICKSEL": "Quick Select",
|
"GAME_ACTION_QUICKSEL": "Quick Select",
|
||||||
"GAME_ACTION_CRAFT": "Craft",
|
|
||||||
"GAME_CRAFTING": "Crafting",
|
|
||||||
"GAME_CRAFTABLE_ITEMS": "Craftable Items",
|
|
||||||
"MENU_LABEL_RENAME": "Rename",
|
|
||||||
"GAME_ACTION_TELEPORT": "Teleport",
|
"GAME_ACTION_TELEPORT": "Teleport",
|
||||||
"CONTEXT_PLACE_COORDINATE": "Coordinate"
|
"GAME_CRAFTABLE_ITEMS": "Craftable Items",
|
||||||
|
"GAME_CRAFTING": "Crafting",
|
||||||
|
"GAME_INVENTORY_BLOCKS": "Blocks",
|
||||||
|
"GAME_INVENTORY_FAVORITES": "Favorites",
|
||||||
|
"GAME_INVENTORY_INGREDIENTS": "Ingredients",
|
||||||
|
"GAME_INVENTORY_POTIONS": "Potions",
|
||||||
|
"GAME_INVENTORY_REGISTER": "Register",
|
||||||
|
"GAME_INVENTORY_WALLS": "Walls"
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,20 @@
|
|||||||
{
|
{
|
||||||
|
"BLOCK_STONE_DEEP": "Deepstone",
|
||||||
|
"BLOCK_SCAFFOLDING_NORMAL": "Scaffolding",
|
||||||
|
"BLOCK_STONE_MARBLE": "Marble",
|
||||||
|
|
||||||
|
"ITEM_CALENDAR": "Calendar",
|
||||||
|
"ITEM_LOGIC_SIGNAL_EMITTER": "Logic Signal Emitter",
|
||||||
|
"ITEM_STORAGE_CHEST": "Storage Chest",
|
||||||
|
"ITEM_TIKI_TORCH": "Tiki Torch",
|
||||||
|
"ITEM_TYPEWRITER": "Typewriter",
|
||||||
|
"ITEM_WIRE": "Wire",
|
||||||
|
"ITEM_WIRE_CUTTER": "Wire Cutter",
|
||||||
|
|
||||||
"ACTORBLOCK_ALLOW_MOVE_DOWN": "Urist Arôlcustith",
|
"ACTORBLOCK_ALLOW_MOVE_DOWN": "Urist Arôlcustith",
|
||||||
"ACTORBLOCK_FULL_COLLISION": "Urist Berdanrifot",
|
"ACTORBLOCK_FULL_COLLISION": "Urist Berdanrifot",
|
||||||
"ACTORBLOCK_NO_COLLISION": "Urist Zafal",
|
"ACTORBLOCK_NO_COLLISION": "Urist Zafal",
|
||||||
"ACTORBLOCK_NO_PASS_RIGHT": "Urist McPassLeft",
|
"ACTORBLOCK_NO_PASS_RIGHT": "Urist McPassLeft",
|
||||||
"ACTORBLOCK_NO_PASS_LEFT": "Urist McPassRight",
|
"ACTORBLOCK_NO_PASS_LEFT": "Urist McPassRight",
|
||||||
"ACTORBLOCK_TILING_PLACEHOLDER": "Urist Berdanurdim",
|
"ACTORBLOCK_TILING_PLACEHOLDER": "Urist Berdanurdim"
|
||||||
|
|
||||||
"BLOCK_STONE_DEEP": "Deepstone",
|
|
||||||
"BLOCK_SCAFFOLDING_NORMAL": "Scaffolding",
|
|
||||||
"BLOCK_STONE_MARBLE": "Marble",
|
|
||||||
|
|
||||||
"ITEM_STORAGE_CHEST": "Storage Chest",
|
|
||||||
"ITEM_WIRE": "Wire",
|
|
||||||
"ITEM_WIRE_CUTTER": "Wire Cutter",
|
|
||||||
"ITEM_LOGIC_SIGNAL_EMITTER": "Logic Signal Emitter",
|
|
||||||
"ITEM_TIKI_TORCH": "Tiki Torch"
|
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "This is a world currently playing."
|
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "This is a world currently playing.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_1": "Copy the Avatar Code into the clipboard, then hit the Paste button below.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_2": ""
|
||||||
}
|
}
|
||||||
16
assets/mods/basegame/locales/koKR/calendar.json
Normal file
16
assets/mods/basegame/locales/koKR/calendar.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"MENU_CALENDAR_CALENDAR": "달력",
|
||||||
|
"MENU_CALENDAR_EVENTS": "일정",
|
||||||
|
"MENU_CALENDAR_ADD_NEW_EVENT": "새 일정 추가",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_SPRING": "봄",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_SUMMER": "여름",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_AUTUMN": "가을",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_WINTER": "겨울",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_SPRI": "봄",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_SUMM": "여름",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_AUTM": "가을",
|
||||||
|
"CONTEXT_CALENDAR_SEASON_WINT": "겨울",
|
||||||
|
"CONTEXT_CALENDAR_DATE_FORMAT_Y": "{0}년",
|
||||||
|
"CONTEXT_CALENDAR_DATE_FORMAT_YMD": "{0}년 {1} {2}일",
|
||||||
|
"CONTEXT_CALENDAR_DATE_FORMAT_YMD_DDD": "{0}년 {1} {2}일 {3}"
|
||||||
|
}
|
||||||
@@ -1,24 +1,25 @@
|
|||||||
{
|
{
|
||||||
|
"CONTEXT_GENERATOR_SEED": "시드",
|
||||||
|
"CONTEXT_ITEM_MAP": "지도",
|
||||||
|
"CONTEXT_ITEM_TOOL_PLURAL": "도구",
|
||||||
|
"CONTEXT_PLACE_COORDINATE": "좌표",
|
||||||
|
"CONTEXT_WORLD_COUNT": "새계: ",
|
||||||
"CONTEXT_WORLD_NEW": "새 세계",
|
"CONTEXT_WORLD_NEW": "새 세계",
|
||||||
"MENU_LABEL_DELETE_WORLD": "새계 삭제",
|
"MENU_LABEL_DELETE_WORLD": "새계 삭제",
|
||||||
"CONTEXT_WORLD_COUNT": "새계: ",
|
|
||||||
"MENU_MONITOR_CALI_TITLE": "모니터 확인",
|
|
||||||
"GAME_INVENTORY_INGREDIENTS": "재료",
|
|
||||||
"GAME_INVENTORY_POTIONS": "물약",
|
|
||||||
"GAME_INVENTORY_BLOCKS": "블록",
|
|
||||||
"GAME_INVENTORY_WALLS": "벽지",
|
|
||||||
"CONTEXT_ITEM_TOOL_PLURAL": "도구",
|
|
||||||
"GAME_INVENTORY_FAVORITES": "즐겨찾기",
|
|
||||||
"GAME_INVENTORY_REGISTER": "등록하기",
|
|
||||||
"MENU_LABEL_MENU": "메뉴",
|
"MENU_LABEL_MENU": "메뉴",
|
||||||
"CONTEXT_ITEM_MAP": "지도",
|
"MENU_LABEL_PREV_SAVES": "이전 세이브",
|
||||||
"CONTEXT_GENERATOR_SEED": "시드",
|
"MENU_LABEL_RENAME": "이름 바꾸기",
|
||||||
|
"MENU_MONITOR_CALI_TITLE": "모니터 확인",
|
||||||
|
"GAME_ACTION_CRAFT": "제작하기",
|
||||||
"GAME_ACTION_GRAPPLE": "매달리기",
|
"GAME_ACTION_GRAPPLE": "매달리기",
|
||||||
"GAME_ACTION_QUICKSEL": "빠른 선택",
|
"GAME_ACTION_QUICKSEL": "빠른 선택",
|
||||||
"GAME_ACTION_CRAFT": "제작하기",
|
|
||||||
"GAME_CRAFTING": "제작",
|
|
||||||
"GAME_CRAFTABLE_ITEMS": "제작 가능한 아이템",
|
|
||||||
"MENU_LABEL_RENAME": "이름 바꾸기",
|
|
||||||
"GAME_ACTION_TELEPORT": "텔레포트하기",
|
"GAME_ACTION_TELEPORT": "텔레포트하기",
|
||||||
"CONTEXT_PLACE_COORDINATE": "좌표"
|
"GAME_CRAFTABLE_ITEMS": "제작 가능한 아이템",
|
||||||
|
"GAME_CRAFTING": "제작",
|
||||||
|
"GAME_INVENTORY_BLOCKS": "블록",
|
||||||
|
"GAME_INVENTORY_FAVORITES": "즐겨찾기",
|
||||||
|
"GAME_INVENTORY_INGREDIENTS": "재료",
|
||||||
|
"GAME_INVENTORY_POTIONS": "물약",
|
||||||
|
"GAME_INVENTORY_REGISTER": "등록하기",
|
||||||
|
"GAME_INVENTORY_WALLS": "벽지"
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,11 @@
|
|||||||
"BLOCK_SCAFFOLDING_NORMAL": "발판",
|
"BLOCK_SCAFFOLDING_NORMAL": "발판",
|
||||||
"BLOCK_STONE_MARBLE": "대리석",
|
"BLOCK_STONE_MARBLE": "대리석",
|
||||||
|
|
||||||
"ITEM_STORAGE_CHEST": "보관상자",
|
"ITEM_CALENDAR": "달력",
|
||||||
"ITEM_WIRE": "전선",
|
|
||||||
"ITEM_WIRE_CUTTER": "전선 절단기",
|
|
||||||
"ITEM_LOGIC_SIGNAL_EMITTER": "신호발생기",
|
"ITEM_LOGIC_SIGNAL_EMITTER": "신호발생기",
|
||||||
"ITEM_TIKI_TORCH": "티키 토치"
|
"ITEM_STORAGE_CHEST": "보관상자",
|
||||||
|
"ITEM_TIKI_TORCH": "티키 토치",
|
||||||
|
"ITEM_TYPEWRITER": "타자기",
|
||||||
|
"ITEM_WIRE": "전선",
|
||||||
|
"ITEM_WIRE_CUTTER": "전선 절단기"
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "현재 플레이 중인 월드입니다."
|
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "현재 플레이 중인 월드입니다.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_1": "아바타 코드를 클립보드에 복사한 다음, 아래의 붙여넣기 버튼을 눌러주세요.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_2": ""
|
||||||
}
|
}
|
||||||
BIN
assets/mods/basegame/sprites/fixtures/calendar.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/fixtures/calendar.tga
LFS
Normal file
Binary file not shown.
@@ -2,7 +2,21 @@
|
|||||||
"skyboxGradColourMap": "generic_skybox.tga",
|
"skyboxGradColourMap": "generic_skybox.tga",
|
||||||
"daylightClut": "clut_daylight.tga",
|
"daylightClut": "clut_daylight.tga",
|
||||||
"classification": "generic",
|
"classification": "generic",
|
||||||
"extraImages": [
|
"cloudChance": 250,
|
||||||
|
"cloudGamma": [0.48, 1.8],
|
||||||
]
|
"cloudGammaVariance": [0.1, 0.1],
|
||||||
|
"windSpeed": 10.25,
|
||||||
|
"windSpeedVariance": 1.0,
|
||||||
|
"clouds": {
|
||||||
|
"cumulonimbus": {
|
||||||
|
"filename": "cloud_large.png", "tw": 2048, "th": 1024, "probability": 0.2,
|
||||||
|
"baseScale": 2.0, "scaleVariance": 0.3333333,
|
||||||
|
"altLow": 80, "altHigh": 120
|
||||||
|
},
|
||||||
|
"cumulus": {
|
||||||
|
"filename": "cloud_normal.png", "tw": 1024, "th": 512, "probability": 1.0,
|
||||||
|
"baseScale": 1.0, "scaleVariance": 0.6,
|
||||||
|
"altLow": 80, "altHigh": 800
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"globalLight": "generic_light.tga",
|
|
||||||
"skyboxGradColourMap": "generic_skybox.tga",
|
|
||||||
"classification": "genericrain",
|
|
||||||
"extraImages": [
|
|
||||||
"raindrop.tga"
|
|
||||||
],
|
|
||||||
"mixFrom": "__CURRENTWEATHER",
|
|
||||||
"mixPercentage": 80.0
|
|
||||||
}
|
|
||||||
27
assets/mods/basegame/weathers/WeatherOvercast.json
Normal file
27
assets/mods/basegame/weathers/WeatherOvercast.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"skyboxGradColourMap": "generic_skybox.tga",
|
||||||
|
"daylightClut": "clut_daylight.tga",
|
||||||
|
"classification": "overcast",
|
||||||
|
"cloudChance": 300,
|
||||||
|
"cloudGamma": [2.2, 2.0],
|
||||||
|
"cloudGammaVariance": [0.1, 0.1],
|
||||||
|
"windSpeed": 10.45,
|
||||||
|
"windSpeedVariance": 1.0,
|
||||||
|
"clouds": {
|
||||||
|
"cumulus": {
|
||||||
|
"filename": "cloud_normal.png", "tw": 1024, "th": 512, "probability": 0.1,
|
||||||
|
"baseScale": 0.8, "scaleVariance": 0.6,
|
||||||
|
"altLow": 80, "altHigh": 800
|
||||||
|
},
|
||||||
|
"cumulonimbus": {
|
||||||
|
"filename": "cloud_large.png", "tw": 2048, "th": 1024, "probability": 0.4,
|
||||||
|
"baseScale": 2.0, "scaleVariance": 0.3333333,
|
||||||
|
"altLow": 90, "altHigh": 120
|
||||||
|
},
|
||||||
|
"nimbostratus": {
|
||||||
|
"filename": "cloud_wide.png", "tw": 4096, "th": 1024, "probability": 1.0,
|
||||||
|
"baseScale": 4.0, "scaleVariance": 0.1,
|
||||||
|
"altLow": 100, "altHigh": 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/mods/basegame/weathers/cloud_large.kra
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_large.kra
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/weathers/cloud_large.png
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_large.png
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/weathers/cloud_normal.kra
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_normal.kra
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/weathers/cloud_normal.png
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_normal.png
LFS
Normal file
Binary file not shown.
26
assets/mods/basegame/weathers/cloud_texture_instruction.md
Normal file
26
assets/mods/basegame/weathers/cloud_texture_instruction.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
## actually blending
|
||||||
|
1. On Krita, load the cloudmap
|
||||||
|
2. Select and isolate suitable piece of the cloud
|
||||||
|
3. With liquefying brush, make the bottom flat
|
||||||
|
4. On new tab, load the solidmap
|
||||||
|
5. Resize the solidmap to 1024x1024
|
||||||
|
6. Rotate the solidmap by 30 deg or so
|
||||||
|
7. Overlay the processed solidmap to the cloudmap, opacity=30%
|
||||||
|
8. With airbrush tool, manually add the shade (see cloud_normal.kra to get the gist of it)
|
||||||
|
|
||||||
|
### cloudmap
|
||||||
|
1. On GIMP, prepare 4096x4096 canvas
|
||||||
|
2. Create Simplex Noise with following parameters:
|
||||||
|
- Scale: arbitrary (0.05 - 0.2)
|
||||||
|
- Iterations: MAX
|
||||||
|
- Seed: anything but 0
|
||||||
|
|
||||||
|
### solidmap
|
||||||
|
1. On GIMP, prepare 4096x4096 canvas
|
||||||
|
2. Create Solid Noise with following parameters:
|
||||||
|
- XY Size: 16.0
|
||||||
|
- Detail: MAX
|
||||||
|
- Tileable: check
|
||||||
|
- Turbulent: check
|
||||||
|
- Seed: anything but 0
|
||||||
|
|
||||||
BIN
assets/mods/basegame/weathers/cloud_wide.kra
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_wide.kra
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/weathers/cloud_wide.png
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_wide.png
LFS
Normal file
Binary file not shown.
@@ -3,7 +3,8 @@ if (( $EUID == 0 )); then echo "The build process is not meant to be run with ro
|
|||||||
|
|
||||||
cd "${0%/*}"
|
cd "${0%/*}"
|
||||||
SRCFILES="terrarummac_arm"
|
SRCFILES="terrarummac_arm"
|
||||||
DESTDIR="out/TerrarumMac.arm.app"
|
APPDIR="./TerrarumMac.arm.app"
|
||||||
|
DESTDIR="out/$APPDIR"
|
||||||
RUNTIME="runtime-osx-arm"
|
RUNTIME="runtime-osx-arm"
|
||||||
|
|
||||||
if [ ! -d "../assets_release" ]; then
|
if [ ! -d "../assets_release" ]; then
|
||||||
@@ -34,4 +35,8 @@ cp -r "../assets_release" $DESTDIR/Contents/MacOS/
|
|||||||
mv $DESTDIR/Contents/MacOS/assets_release $DESTDIR/Contents/MacOS/assets
|
mv $DESTDIR/Contents/MacOS/assets_release $DESTDIR/Contents/MacOS/assets
|
||||||
cp "../out/TerrarumBuild.jar" $DESTDIR/Contents/MacOS/out/
|
cp "../out/TerrarumBuild.jar" $DESTDIR/Contents/MacOS/out/
|
||||||
|
|
||||||
|
cd "out"
|
||||||
|
rm $APPDIR.zip
|
||||||
|
7z a -tzip $APPDIR.zip $APPDIR
|
||||||
|
|
||||||
echo "Build successful: $DESTDIR"
|
echo "Build successful: $DESTDIR"
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ if (( $EUID == 0 )); then echo "The build process is not meant to be run with ro
|
|||||||
|
|
||||||
cd "${0%/*}"
|
cd "${0%/*}"
|
||||||
SRCFILES="terrarummac_x86"
|
SRCFILES="terrarummac_x86"
|
||||||
DESTDIR="out/TerrarumMac.x86.app"
|
APPDIR="./TerrarumMac.x86.app"
|
||||||
|
DESTDIR="out/$APPDIR"
|
||||||
RUNTIME="runtime-osx-x86"
|
RUNTIME="runtime-osx-x86"
|
||||||
|
|
||||||
if [ ! -d "../assets_release" ]; then
|
if [ ! -d "../assets_release" ]; then
|
||||||
@@ -34,4 +35,8 @@ cp -r "../assets_release" $DESTDIR/Contents/MacOS/
|
|||||||
mv $DESTDIR/Contents/MacOS/assets_release $DESTDIR/Contents/MacOS/assets
|
mv $DESTDIR/Contents/MacOS/assets_release $DESTDIR/Contents/MacOS/assets
|
||||||
cp "../out/TerrarumBuild.jar" $DESTDIR/Contents/MacOS/out/
|
cp "../out/TerrarumBuild.jar" $DESTDIR/Contents/MacOS/out/
|
||||||
|
|
||||||
|
cd "out"
|
||||||
|
rm $APPDIR.zip
|
||||||
|
7z a -tzip $APPDIR.zip $APPDIR
|
||||||
|
|
||||||
echo "Build successful: $DESTDIR"
|
echo "Build successful: $DESTDIR"
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ mv $DESTDIR/assets_release $DESTDIR/assets
|
|||||||
cp "../out/TerrarumBuild.jar" $DESTDIR/out/
|
cp "../out/TerrarumBuild.jar" $DESTDIR/out/
|
||||||
|
|
||||||
# Temporary solution: zip everything
|
# Temporary solution: zip everything
|
||||||
|
rm "out/TerrarumWindows.x86.zip"
|
||||||
zip -r -9 -l "out/TerrarumWindows.x86.zip" $DESTDIR
|
zip -r -9 -l "out/TerrarumWindows.x86.zip" $DESTDIR
|
||||||
rm -rf $DESTDIR || true
|
rm -rf $DESTDIR || true
|
||||||
echo "Build successful: $DESTDIR"
|
echo "Build successful: $DESTDIR"
|
||||||
|
|||||||
28
buildapp/make_assets_release.sh
Executable file
28
buildapp/make_assets_release.sh
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if (( $EUID == 0 )); then echo "The build process is not meant to be run with root privilege, exiting now." >&2; exit 1; fi
|
||||||
|
|
||||||
|
cd "${0%/*}"
|
||||||
|
DESTDIR="../assets_release"
|
||||||
|
|
||||||
|
rm -r $DESTDIR
|
||||||
|
cp -r "../assets" $DESTDIR
|
||||||
|
|
||||||
|
rm $DESTDIR/loopey.wav
|
||||||
|
rm $DESTDIR/ktGrepExample.kts
|
||||||
|
rm $DESTDIR/batchtest.txt
|
||||||
|
rm $DESTDIR/test_texture.tga
|
||||||
|
rm $DESTDIR/worldbacktest.tga
|
||||||
|
rm -r $DESTDIR/books
|
||||||
|
rm $DESTDIR/clut/skybox.tga
|
||||||
|
rm $DESTDIR/graphics/*.bat
|
||||||
|
rm $DESTDIR/keylayout/*.not_ime
|
||||||
|
rm $DESTDIR/mods/basegame/blocks/*.gz
|
||||||
|
rm $DESTDIR/mods/basegame/blocks/*.txt
|
||||||
|
rm $DESTDIR/mods/basegame/weathers/*.txt
|
||||||
|
rm $DESTDIR/mods/basegame/weathers/*.md
|
||||||
|
rm $DESTDIR/mods/basegame/weathers/*.kra
|
||||||
|
rm -r $DESTDIR/mods/basegame/sounds
|
||||||
|
rm -r $DESTDIR/mods/dwarventech
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
|
#include <windows.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <tchar.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
return system(".\\out\\runtime-windows-x86\\bin\\Terrarum.exe -jar .\\out\\TerrarumBuild.jar");
|
|
||||||
|
ShellExecute(NULL, "open", "\".\\out\\runtime-windows-x86\\bin\\Terrarum.exe\"", "-jar \".\\out\\TerrarumBuild.jar\"", NULL, SW_HIDE);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
//return system(".\\out\\runtime-windows-x86\\bin\\Terrarum.exe -jar .\\out\\TerrarumBuild.jar");
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package com.badlogic.gdx.graphics.glutils;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Application;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.GL30;
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||||
|
import net.torvald.terrarum.App;
|
||||||
|
|
||||||
|
// typealias Float16FrameBuffer = FloatFrameBuffer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-16.
|
||||||
|
*/
|
||||||
|
public class Float16FrameBuffer extends FrameBuffer {
|
||||||
|
|
||||||
|
Float16FrameBuffer () {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a GLFrameBuffer from the specifications provided by bufferBuilder
|
||||||
|
*
|
||||||
|
* @param bufferBuilder **/
|
||||||
|
protected Float16FrameBuffer (GLFrameBufferBuilder<? extends GLFrameBuffer<Texture>> bufferBuilder) {
|
||||||
|
super(bufferBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a new FrameBuffer with a float backing texture, having the given dimensions and potentially a depth buffer
|
||||||
|
* attached.
|
||||||
|
*
|
||||||
|
* @param width the width of the framebuffer in pixels
|
||||||
|
* @param height the height of the framebuffer in pixels
|
||||||
|
* @param hasDepth whether to attach a depth buffer
|
||||||
|
* @throws GdxRuntimeException in case the FrameBuffer could not be created */
|
||||||
|
public Float16FrameBuffer (int width, int height, boolean hasDepth) {
|
||||||
|
if (App.isAppleM) { // disable float framebuffer for Apple M chips
|
||||||
|
FrameBufferBuilder bufferBuilder = new FrameBufferBuilder(width, height);
|
||||||
|
bufferBuilder.addColorTextureAttachment(GL20.GL_RGBA, GL20.GL_RGBA, GL20.GL_UNSIGNED_SHORT); // but 16bpp int works perfectly?!
|
||||||
|
if (hasDepth) bufferBuilder.addBasicDepthRenderBuffer();
|
||||||
|
this.bufferBuilder = bufferBuilder;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FloatFrameBufferBuilder bufferBuilder = new FloatFrameBufferBuilder(width, height);
|
||||||
|
bufferBuilder.addFloatAttachment(GL30.GL_RGBA16F, GL30.GL_RGBA, GL30.GL_FLOAT, false); // FIXME sporadic black screen on GL_RGBA16F? or maybe it was Plasma bugging out?
|
||||||
|
if (hasDepth) bufferBuilder.addBasicDepthRenderBuffer();
|
||||||
|
this.bufferBuilder = bufferBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Texture createTexture (FrameBufferTextureAttachmentSpec attachmentSpec) {
|
||||||
|
if (App.isAppleM) {
|
||||||
|
GLOnlyTextureData data = new GLOnlyTextureData(bufferBuilder.width, bufferBuilder.height, 0, attachmentSpec.internalFormat,
|
||||||
|
attachmentSpec.format, attachmentSpec.type);
|
||||||
|
Texture result = new Texture(data);
|
||||||
|
result.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
|
||||||
|
result.setWrap(Texture.TextureWrap.ClampToEdge, Texture.TextureWrap.ClampToEdge);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FloatTextureData data = new FloatTextureData(bufferBuilder.width, bufferBuilder.height, attachmentSpec.internalFormat,
|
||||||
|
attachmentSpec.format, attachmentSpec.type, attachmentSpec.isGpuOnly);
|
||||||
|
Texture result = new Texture(data);
|
||||||
|
result.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
|
||||||
|
result.setWrap(Texture.TextureWrap.ClampToEdge, Texture.TextureWrap.ClampToEdge);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -248,6 +248,10 @@ final public class FastMath {
|
|||||||
return interpolateCatmullRom(u, 0.5f, p0, p1, p2, p3);
|
return interpolateCatmullRom(u, 0.5f, p0, p1, p2, p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float interpolateCatmullRom(float u, float[] ps) {
|
||||||
|
return interpolateCatmullRom(u, 0.5f, ps[0], ps[1], ps[2], ps[3]);
|
||||||
|
}
|
||||||
|
|
||||||
/**Interpolate a spline between at least 4 control points following the Catmull-Rom equation.
|
/**Interpolate a spline between at least 4 control points following the Catmull-Rom equation.
|
||||||
* here is the interpolation matrix
|
* here is the interpolation matrix
|
||||||
* m = [ 0.0 1.0 0.0 0.0 ]
|
* m = [ 0.0 1.0 0.0 0.0 ]
|
||||||
@@ -331,8 +335,7 @@ final public class FastMath {
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*public static float interpolateHermite(float scale, float p0, float p1, float p2, float p3) {
|
||||||
public static float interpolateHermite(float scale, float p0, float p1, float p2, float p3) {
|
|
||||||
// return interpolateHermite(scale, p0, p1, p2, p3, 0f, 0f);
|
// return interpolateHermite(scale, p0, p1, p2, p3, 0f, 0f);
|
||||||
float mu2 = scale * scale;
|
float mu2 = scale * scale;
|
||||||
float mu3 = mu2 * scale;
|
float mu3 = mu2 * scale;
|
||||||
@@ -350,7 +353,7 @@ final public class FastMath {
|
|||||||
float a3 = -2*mu3 + 3*mu2 + 0;
|
float a3 = -2*mu3 + 3*mu2 + 0;
|
||||||
|
|
||||||
return a0*p1 + a1*m0 + a2*m1 + a3*p2;
|
return a0*p1 + a1*m0 + a2*m1 + a3*p2;
|
||||||
}
|
}*/
|
||||||
//public static float interpolateHermite(float scale, float p0, float p1, float p2, float p3, float tension, float bias) {}
|
//public static float interpolateHermite(float scale, float p0, float p1, float p2, float p3, float tension, float bias) {}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -192,6 +192,16 @@ fun CIEXYZ.toColorRaw(): Color {
|
|||||||
return Color(rgb.r, rgb.g, rgb.b, rgb.alpha)
|
return Color(rgb.r, rgb.g, rgb.b, rgb.alpha)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun CIEXYZ.toYXY(): CIEYXY {
|
||||||
|
val dot = this.X + this.Y + this.Z
|
||||||
|
return CIEYXY(
|
||||||
|
this.Y,
|
||||||
|
this.X / dot,
|
||||||
|
this.Y / dot,
|
||||||
|
this.alpha
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun CIEYXY.toXYZ(): CIEXYZ {
|
fun CIEYXY.toXYZ(): CIEXYZ {
|
||||||
return CIEXYZ(x * yy / y, yy, (1f - x - y) * yy / y)
|
return CIEXYZ(x * yy / y, yy, (1f - x - y) * yy / y)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,16 +12,14 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|||||||
import net.torvald.unicode.EMDASH
|
import net.torvald.unicode.EMDASH
|
||||||
import net.torvald.colourutil.*
|
import net.torvald.colourutil.*
|
||||||
import net.torvald.parametricsky.datasets.DatasetCIEXYZ
|
import net.torvald.parametricsky.datasets.DatasetCIEXYZ
|
||||||
import net.torvald.parametricsky.datasets.DatasetRGB
|
|
||||||
import net.torvald.parametricsky.datasets.DatasetSpectral
|
|
||||||
import net.torvald.terrarum.abs
|
import net.torvald.terrarum.abs
|
||||||
|
import net.torvald.terrarum.clut.Skybox
|
||||||
|
import net.torvald.terrarum.clut.Skybox.coerceInSmoothly
|
||||||
|
import net.torvald.terrarum.clut.Skybox.mapCircle
|
||||||
import net.torvald.terrarum.inUse
|
import net.torvald.terrarum.inUse
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.HALF_PI
|
import net.torvald.terrarum.modulebasegame.worldgenerator.HALF_PI
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.TWO_PI
|
|
||||||
import java.awt.BorderLayout
|
import java.awt.BorderLayout
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
import java.awt.FlowLayout
|
|
||||||
import java.awt.GridLayout
|
|
||||||
import java.lang.Math.pow
|
import java.lang.Math.pow
|
||||||
import javax.swing.*
|
import javax.swing.*
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
@@ -94,7 +92,16 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
|||||||
if (turbidity <= 0) throw IllegalStateException()
|
if (turbidity <= 0) throw IllegalStateException()
|
||||||
|
|
||||||
// we need to use different model-state to accommodate different albedo for each spectral band but oh well...
|
// we need to use different model-state to accommodate different albedo for each spectral band but oh well...
|
||||||
genTexLoop(model)
|
genTexLoop(model, elevation)
|
||||||
|
// println("$elevation\t${ymaxDisp.text}\t${ymaxDisp2.text}")
|
||||||
|
|
||||||
|
|
||||||
|
/*for (elev in -75..75) {
|
||||||
|
val elevation = Math.toRadians(elev.toDouble())
|
||||||
|
val model = ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevation.abs())
|
||||||
|
genTexLoop(model, elevation)
|
||||||
|
println("$elev\t${ymaxDisp.text}\t${ymaxDisp2.text}")
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
val tex = Texture(oneScreen)
|
val tex = Texture(oneScreen)
|
||||||
@@ -127,7 +134,7 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val outTexWidth = 1
|
val outTexWidth = 1
|
||||||
val outTexHeight = 256
|
val outTexHeight = 128
|
||||||
|
|
||||||
private fun Float.scaleFun() =
|
private fun Float.scaleFun() =
|
||||||
(1f - 1f / 2f.pow(this/6f)) * 0.97f
|
(1f - 1f / 2f.pow(this/6f)) * 0.97f
|
||||||
@@ -142,14 +149,20 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val elevation1 = -Math.toDegrees(elevation)
|
// maths model: https://www.desmos.com/calculator/cwi7iyzygg
|
||||||
val elevation2 = -Math.toDegrees(elevation) / 28.5
|
|
||||||
val scale = (1f - (1f - 1f / 1.8.pow(elevation1)) * 0.97f).toFloat()
|
val x = -Math.toDegrees(elevation).toFloat()
|
||||||
val scale2 = (1.0 - (elevation2.pow(E) / E.pow(elevation2))*0.8).toFloat()
|
// val elevation2 = -Math.toDegrees(elevation) / 28.5
|
||||||
|
val p = 3.5f
|
||||||
|
val q = 7.5f
|
||||||
|
val s = -0.2f
|
||||||
|
val f = (1f - (1f - 1f / 1.8f.pow(x)) * 0.97f).toFloat()
|
||||||
|
// val g = (1.0 - (elevation2.pow(E) / E.pow(elevation2))*0.8).toFloat()
|
||||||
|
val h = ((x / q).pow(p) + 1f).pow(s)
|
||||||
CIEXYZ(
|
CIEXYZ(
|
||||||
this.X.scaleFun() * scale * scale2,
|
this.X.scaleFun() * f * h,
|
||||||
this.Y.scaleFun() * scale * scale2,
|
this.Y.scaleFun() * f * h,
|
||||||
this.Z.scaleFun() * scale * scale2,
|
this.Z.scaleFun() * f * h,
|
||||||
this.alpha
|
this.alpha
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -161,7 +174,7 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
|||||||
* Generated texture is as if you took the panorama picture of sky: up 70deg to horizon, east-south-west;
|
* Generated texture is as if you took the panorama picture of sky: up 70deg to horizon, east-south-west;
|
||||||
* with sun not moving (sun is at exact south, sun's height is adjustable)
|
* with sun not moving (sun is at exact south, sun's height is adjustable)
|
||||||
*/
|
*/
|
||||||
private fun genTexLoop(state: ArHosekSkyModelState) {
|
private fun genTexLoop(state: ArHosekSkyModelState, elevation: Double) {
|
||||||
|
|
||||||
fun normaliseY(y: Double): Float {
|
fun normaliseY(y: Double): Float {
|
||||||
var v = y.coerceAtLeast(0.0)
|
var v = y.coerceAtLeast(0.0)
|
||||||
@@ -175,6 +188,7 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
|||||||
val ys2 = ArrayList<Float>()
|
val ys2 = ArrayList<Float>()
|
||||||
|
|
||||||
val halfHeight = oneScreen.height * 0.5
|
val halfHeight = oneScreen.height * 0.5
|
||||||
|
val elevationDeg = Math.toDegrees(elevation)
|
||||||
|
|
||||||
for (x in 0 until oneScreen.width) {
|
for (x in 0 until oneScreen.width) {
|
||||||
for (y in 0 until oneScreen.height) {
|
for (y in 0 until oneScreen.height) {
|
||||||
@@ -186,17 +200,19 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
|||||||
val theta = sqrt(xf*xf + yf*yf) * HALF_PI*/
|
val theta = sqrt(xf*xf + yf*yf) * HALF_PI*/
|
||||||
|
|
||||||
// AM-PM mapping (use with WIDTH=1)
|
// AM-PM mapping (use with WIDTH=1)
|
||||||
var yf = (y * 2.0 / oneScreen.height) % 1.0
|
val yp = y % (oneScreen.height / 2)
|
||||||
if (elevation < 0) yf *= 1.0 - pow(-elevation / HALF_PI, 0.333)
|
val yi = yp - 3
|
||||||
|
val xf = -elevationDeg / 90.0
|
||||||
|
var yf = (yi / 58.0).coerceIn(0.0, 1.0).mapCircle().coerceInSmoothly(0.0, 0.95)
|
||||||
|
if (elevationDeg < 0) yf *= Skybox.superellipsoidDecay(1.0 / 3.0, xf)
|
||||||
|
val theta = yf * HALF_PI
|
||||||
val gamma = if (y < halfHeight) HALF_PI else 3 * HALF_PI
|
val gamma = if (y < halfHeight) HALF_PI else 3 * HALF_PI
|
||||||
val theta = yf.mapCircle() * HALF_PI
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val xyz = CIEXYZ(
|
val xyz = CIEXYZ(
|
||||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 0).toFloat(),
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 0).toFloat(),
|
||||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 1).toFloat(),
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 1).toFloat(),
|
||||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 2).toFloat()
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 2).toFloat(),
|
||||||
)
|
)
|
||||||
val xyz2 = xyz.scaleToFit(elevation)
|
val xyz2 = xyz.scaleToFit(elevation)
|
||||||
ys.add(xyz.Y)
|
ys.add(xyz.Y)
|
||||||
@@ -204,12 +220,12 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
|||||||
val rgb = xyz2.toRGB().toColor()
|
val rgb = xyz2.toRGB().toColor()
|
||||||
rgb.a = 1f
|
rgb.a = 1f
|
||||||
|
|
||||||
val rgb2 = Color(
|
/*val rgb2 = Color(
|
||||||
((rgb.r * 255f).roundToInt() xor 0xAA) / 255f,
|
((rgb.r * 255f).roundToInt() xor 0xAA) / 255f,
|
||||||
((rgb.g * 255f).roundToInt() xor 0xAA) / 255f,
|
((rgb.g * 255f).roundToInt() xor 0xAA) / 255f,
|
||||||
((rgb.b * 255f).roundToInt() xor 0xAA) / 255f,
|
((rgb.b * 255f).roundToInt() xor 0xAA) / 255f,
|
||||||
rgb.a
|
rgb.a
|
||||||
)
|
)*/
|
||||||
|
|
||||||
oneScreen.setColor(rgb)
|
oneScreen.setColor(rgb)
|
||||||
oneScreen.drawPixel(x, y)
|
oneScreen.drawPixel(x, y)
|
||||||
|
|||||||
@@ -62,9 +62,11 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
public static final String GAME_NAME = TerrarumAppConfiguration.GAME_NAME;
|
public static final String GAME_NAME = TerrarumAppConfiguration.GAME_NAME;
|
||||||
public static final long VERSION_RAW = TerrarumAppConfiguration.VERSION_RAW;
|
public static final long VERSION_RAW = TerrarumAppConfiguration.VERSION_RAW;
|
||||||
|
public static final String VERSION_TAG = TerrarumAppConfiguration.VERSION_TAG;
|
||||||
|
|
||||||
public static final String getVERSION_STRING() {
|
public static final String getVERSION_STRING() {
|
||||||
return String.format("%d.%d.%d", VERSION_RAW >>> 48, (VERSION_RAW & 0xffff000000L) >>> 24, VERSION_RAW & 0xffffffL);
|
return String.format("%d.%d.%d", VERSION_RAW >>> 48, (VERSION_RAW & 0xffff000000L) >>> 24, VERSION_RAW & 0xffffffL) +
|
||||||
|
(VERSION_TAG.isBlank() ? "" : "-"+VERSION_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -267,12 +269,13 @@ public class App implements ApplicationListener {
|
|||||||
Gdx.gl20.glViewport(0, 0, width, height);
|
Gdx.gl20.glViewport(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final float UPDATE_RATE = 1f / 64f; // apparent framerate will be limited by update rate
|
public static final int TICK_SPEED = 64;
|
||||||
|
public static final float UPDATE_RATE = 1f / TICK_SPEED; // apparent framerate will be limited by update rate
|
||||||
|
|
||||||
private static float loadTimer = 0f;
|
private static float loadTimer = 0f;
|
||||||
private static final float showupTime = 100f / 1000f;
|
private static final float showupTime = 100f / 1000f;
|
||||||
|
|
||||||
private static FloatFrameBuffer renderFBO;
|
private static Float16FrameBuffer renderFBO;
|
||||||
|
|
||||||
public static HashSet<File> tempFilePool = new HashSet<>();
|
public static HashSet<File> tempFilePool = new HashSet<>();
|
||||||
|
|
||||||
@@ -609,19 +612,21 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
private static void processScreenshotRequest(FrameBuffer fb) {
|
private static void processScreenshotRequest(FrameBuffer fb) {
|
||||||
if (screenshotRequested) {
|
if (screenshotRequested) {
|
||||||
|
String msg = "Screenshot taken";
|
||||||
FrameBufferManager.begin(fb);
|
FrameBufferManager.begin(fb);
|
||||||
try {
|
try {
|
||||||
Pixmap p = Pixmap.createFromFrameBuffer(0, 0, fb.getWidth(), fb.getHeight());
|
Pixmap p = Pixmap.createFromFrameBuffer(0, 0, fb.getWidth(), fb.getHeight());
|
||||||
PixmapIO.writePNG(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".png"), p, 9, true);
|
PixmapIO.writePNG(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".png"), p, 9, true);
|
||||||
p.dispose();
|
p.dispose();
|
||||||
Terrarum.INSTANCE.getIngame().sendNotification("Screenshot taken");
|
|
||||||
}
|
}
|
||||||
catch (Throwable e) {
|
catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Terrarum.INSTANCE.getIngame().sendNotification("Failed to take screenshot: "+e.getMessage());
|
msg = ("Failed to take screenshot: "+e.getMessage());
|
||||||
}
|
}
|
||||||
FrameBufferManager.end();
|
FrameBufferManager.end();
|
||||||
screenshotRequested = false;
|
screenshotRequested = false;
|
||||||
|
|
||||||
|
Terrarum.INSTANCE.getIngame().sendNotification(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -750,12 +755,12 @@ public class App implements ApplicationListener {
|
|||||||
(renderFBO.getWidth() != scr.getWidth() ||
|
(renderFBO.getWidth() != scr.getWidth() ||
|
||||||
renderFBO.getHeight() != scr.getHeight())
|
renderFBO.getHeight() != scr.getHeight())
|
||||||
) {
|
) {
|
||||||
renderFBO = new FloatFrameBuffer(
|
renderFBO = new Float16FrameBuffer(
|
||||||
scr.getWidth(),
|
scr.getWidth(),
|
||||||
scr.getHeight(),
|
scr.getHeight(),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
postProcessorOutFBO2 = new FloatFrameBuffer(
|
postProcessorOutFBO2 = new Float16FrameBuffer(
|
||||||
scr.getWidth() * 2,
|
scr.getWidth() * 2,
|
||||||
scr.getHeight() * 2,
|
scr.getHeight() * 2,
|
||||||
false
|
false
|
||||||
@@ -1373,6 +1378,8 @@ public class App implements ApplicationListener {
|
|||||||
* @throws NullPointerException if the specified config simply does not exist.
|
* @throws NullPointerException if the specified config simply does not exist.
|
||||||
*/
|
*/
|
||||||
public static int getConfigInt(String key) {
|
public static int getConfigInt(String key) {
|
||||||
|
if (key == null) return -1;
|
||||||
|
|
||||||
Object cfg = getConfigMaster(key);
|
Object cfg = getConfigMaster(key);
|
||||||
|
|
||||||
if (cfg instanceof Integer) return ((int) cfg);
|
if (cfg instanceof Integer) return ((int) cfg);
|
||||||
|
|||||||
90
src/net/torvald/terrarum/ControlPresets.kt
Normal file
90
src/net/torvald/terrarum/ControlPresets.kt
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Input
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-24.
|
||||||
|
*/
|
||||||
|
object ControlPresets {
|
||||||
|
|
||||||
|
val wasd = hashMapOf<String, Int>(
|
||||||
|
"control_key_up" to Input.Keys.W,
|
||||||
|
"control_key_left" to Input.Keys.A,
|
||||||
|
"control_key_down" to Input.Keys.S,
|
||||||
|
"control_key_right" to Input.Keys.D,
|
||||||
|
|
||||||
|
"control_key_jump" to Input.Keys.SPACE,
|
||||||
|
"control_key_movementaux" to Input.Keys.SHIFT_LEFT, // movement-auxiliary, or hookshot
|
||||||
|
"control_key_inventory" to Input.Keys.Q,
|
||||||
|
"control_key_interact" to Input.Keys.R,
|
||||||
|
"control_key_discard" to Input.Keys.F,
|
||||||
|
"control_key_close" to Input.Keys.X, // this or hard-coded ESC
|
||||||
|
"control_key_zoom" to Input.Keys.Z,
|
||||||
|
|
||||||
|
"control_key_gamemenu" to Input.Keys.TAB,
|
||||||
|
"control_key_crafting" to Input.Keys.E,
|
||||||
|
"control_key_quicksel" to Input.Keys.CONTROL_LEFT, // pie menu is now LShift because CapsLock is actually used by the my bespoke keyboard input
|
||||||
|
)
|
||||||
|
|
||||||
|
val esdf = hashMapOf<String, Int>(
|
||||||
|
"control_key_up" to Input.Keys.E,
|
||||||
|
"control_key_left" to Input.Keys.S,
|
||||||
|
"control_key_down" to Input.Keys.D,
|
||||||
|
"control_key_right" to Input.Keys.F, // ESDF Masterrace
|
||||||
|
|
||||||
|
"control_key_jump" to Input.Keys.SPACE,
|
||||||
|
"control_key_movementaux" to Input.Keys.A, // movement-auxiliary, or hookshot
|
||||||
|
"control_key_inventory" to Input.Keys.Q,
|
||||||
|
"control_key_interact" to Input.Keys.R,
|
||||||
|
"control_key_discard" to Input.Keys.T,
|
||||||
|
"control_key_close" to Input.Keys.C, // this or hard-coded ESC
|
||||||
|
"control_key_zoom" to Input.Keys.Z,
|
||||||
|
|
||||||
|
"control_key_gamemenu" to Input.Keys.TAB,
|
||||||
|
"control_key_crafting" to Input.Keys.W,
|
||||||
|
"control_key_quicksel" to Input.Keys.SHIFT_LEFT, // pie menu is now LShift because CapsLock is actually used by the my bespoke keyboard input
|
||||||
|
)
|
||||||
|
|
||||||
|
val ijkl = hashMapOf<String, Int>(
|
||||||
|
"control_key_up" to Input.Keys.I,
|
||||||
|
"control_key_left" to Input.Keys.J,
|
||||||
|
"control_key_down" to Input.Keys.K,
|
||||||
|
"control_key_right" to Input.Keys.L,
|
||||||
|
|
||||||
|
"control_key_jump" to Input.Keys.SPACE,
|
||||||
|
"control_key_movementaux" to Input.Keys.SEMICOLON, // movement-auxiliary, or hookshot
|
||||||
|
"control_key_inventory" to Input.Keys.P,
|
||||||
|
"control_key_interact" to Input.Keys.U,
|
||||||
|
"control_key_discard" to Input.Keys.Y,
|
||||||
|
"control_key_close" to Input.Keys.M, // this or hard-coded ESC
|
||||||
|
"control_key_zoom" to Input.Keys.SLASH,
|
||||||
|
|
||||||
|
"control_key_gamemenu" to Input.Keys.LEFT_BRACKET,
|
||||||
|
"control_key_crafting" to Input.Keys.O,
|
||||||
|
"control_key_quicksel" to Input.Keys.APOSTROPHE, // pie menu is now LShift because CapsLock is actually used by the my bespoke keyboard input
|
||||||
|
)
|
||||||
|
|
||||||
|
val empty = hashMapOf<String, Int>()
|
||||||
|
|
||||||
|
val presets = hashMapOf( // unordered
|
||||||
|
"WASD" to wasd,
|
||||||
|
"ESDF" to esdf,
|
||||||
|
"IJKL" to ijkl,
|
||||||
|
"Custom" to empty,
|
||||||
|
)
|
||||||
|
|
||||||
|
val presetLabels = listOf( // ordered
|
||||||
|
"WASD",
|
||||||
|
"ESDF",
|
||||||
|
"IJKL",
|
||||||
|
"Custom",
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getKey(label: String?): Int {
|
||||||
|
if (label == null) return -1
|
||||||
|
|
||||||
|
val presetName = App.getConfigString("control_preset_keyboard") ?: "Custom"
|
||||||
|
|
||||||
|
return (presets[presetName] ?: throw IllegalStateException("No such keyboard preset: $presetName")).getOrDefault(label, App.getConfigInt(label))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,8 @@ object DefaultConfig {
|
|||||||
|
|
||||||
"usexinput" to true, // when FALSE, LT+RT input on xbox controller is impossible
|
"usexinput" to true, // when FALSE, LT+RT input on xbox controller is impossible
|
||||||
|
|
||||||
|
"control_preset_keyboard" to "WASD",
|
||||||
|
|
||||||
"control_gamepad_keyn" to 3,
|
"control_gamepad_keyn" to 3,
|
||||||
"control_gamepad_keyw" to 2,
|
"control_gamepad_keyw" to 2,
|
||||||
"control_gamepad_keys" to 0,
|
"control_gamepad_keys" to 0,
|
||||||
|
|||||||
@@ -531,6 +531,9 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
else
|
else
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onConfigChange() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun Lock.lock(body: () -> Unit) {
|
inline fun Lock.lock(body: () -> Unit) {
|
||||||
|
|||||||
@@ -62,9 +62,12 @@ basegame
|
|||||||
* e.g. 0x02010034 will be translated as 2.1.52
|
* e.g. 0x02010034 will be translated as 2.1.52
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const val VERSION_RAW: Long = 0x0000_000003_000002
|
const val VERSION_RAW: Long = 0x0000_000003_000003
|
||||||
// Commit counts up to the Release 0.3.0: 2259
|
// Commit counts up to the Release 0.3.0: 2259
|
||||||
// Commit counts up to the Release 0.3.1: 2278
|
// Commit counts up to the Release 0.3.1: 2278
|
||||||
|
// Commit counts up to the Release 0.3.2: 2732
|
||||||
|
|
||||||
|
const val VERSION_TAG: String = "test002"
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
// CONFIGURATION FOR TILE MAKER //
|
// CONFIGURATION FOR TILE MAKER //
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.badlogic.gdx.math.Matrix4
|
|||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
|
import net.torvald.terrarum.App.IS_DEVELOPMENT_BUILD
|
||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
import net.torvald.terrarum.ui.BasicDebugInfoWindow
|
import net.torvald.terrarum.ui.BasicDebugInfoWindow
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
@@ -150,9 +151,10 @@ object TerrarumPostProcessor : Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// draw dev build notifiers
|
// draw dev build notifiers
|
||||||
if (App.IS_DEVELOPMENT_BUILD && Terrarum.ingame != null) {
|
// omitting this screws up HQ2X render for some reason
|
||||||
|
if (Terrarum.ingame != null) {
|
||||||
batch.inUse {
|
batch.inUse {
|
||||||
batch.color = safeAreaCol
|
batch.color = if (IS_DEVELOPMENT_BUILD) safeAreaCol else colourNull
|
||||||
App.fontGame.draw(it, thisIsDebugStr, 5f, App.scr.height - 24f)
|
App.fontGame.draw(it, thisIsDebugStr, 5f, App.scr.height - 24f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,6 +194,7 @@ object TerrarumPostProcessor : Disposable {
|
|||||||
return outFBO
|
return outFBO
|
||||||
}
|
}
|
||||||
private val rng = HQRNG()
|
private val rng = HQRNG()
|
||||||
|
private val colourNull = Color(0)
|
||||||
|
|
||||||
private fun Double.format(digits: Int) = "%.${digits}f".format(this)
|
private fun Double.format(digits: Int) = "%.${digits}f".format(this)
|
||||||
private fun Float.format(digits: Int) = "%.${digits}f".format(this)
|
private fun Float.format(digits: Int) = "%.${digits}f".format(this)
|
||||||
|
|||||||
@@ -209,8 +209,8 @@ class BlockCodex {
|
|||||||
prop.isSolid = record.boolVal("solid")
|
prop.isSolid = record.boolVal("solid")
|
||||||
//prop.isClear = record.boolVal("clear")
|
//prop.isClear = record.boolVal("clear")
|
||||||
|
|
||||||
prop.isPlatform = prop.tags.contains("PLATFORM")
|
prop.isPlatform = prop.hasTag("PLATFORM")
|
||||||
prop.isActorBlock = prop.tags.contains("ACTORBLOCK")
|
prop.isActorBlock = prop.hasTag("ACTORBLOCK")
|
||||||
|
|
||||||
prop.isWallable = record.boolVal("wall")
|
prop.isWallable = record.boolVal("wall")
|
||||||
prop.maxSupport = record.intVal("grav")
|
prop.maxSupport = record.intVal("grav")
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ class BlockProp {
|
|||||||
BlockCodex[BlockCodex.tileToVirtual[id]!![offset]]._lumCol.lane(channel)
|
BlockCodex[BlockCodex.tileToVirtual[id]!![offset]]._lumCol.lane(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun hasTag(s: String) = tags.contains(s)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param luminosity
|
* @param luminosity
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ fun main() {
|
|||||||
// y: increasing turbidity (1.0 .. 10.0, in steps of 0.333)
|
// y: increasing turbidity (1.0 .. 10.0, in steps of 0.333)
|
||||||
// x: elevations (-75 .. 75 in steps of 1, then albedo of [0.1, 0.3, 0.5, 0.7, 0.9])
|
// x: elevations (-75 .. 75 in steps of 1, then albedo of [0.1, 0.3, 0.5, 0.7, 0.9])
|
||||||
val texh = Skybox.gradSize * Skybox.turbCnt
|
val texh = Skybox.gradSize * Skybox.turbCnt
|
||||||
val texw = Skybox.elevCnt * Skybox.albedoCnt
|
val texw = Skybox.elevCnt * Skybox.albedoCnt * 2
|
||||||
val TGA_HEADER_SIZE = 18
|
val TGA_HEADER_SIZE = 18
|
||||||
|
|
||||||
val bytes = ByteArray(TGA_HEADER_SIZE + texw * texh * 4 + 26)
|
val bytes = ByteArray(TGA_HEADER_SIZE + texw * texh * 4 + 26)
|
||||||
@@ -44,47 +44,50 @@ fun main() {
|
|||||||
println("Generating texture atlas ($texw x $texh)...")
|
println("Generating texture atlas ($texw x $texh)...")
|
||||||
|
|
||||||
// write pixels
|
// write pixels
|
||||||
for (albedo0 in 0 until Skybox.albedoCnt) {
|
for (gammaPair in 0..1) {
|
||||||
val albedo = Skybox.albedos[albedo0]
|
for (albedo0 in 0 until Skybox.albedoCnt) {
|
||||||
println("Albedo=$albedo")
|
val albedo = Skybox.albedos[albedo0]
|
||||||
for (turb0 in 0 until Skybox.turbCnt) {
|
println("Albedo=$albedo")
|
||||||
val turbidity = Skybox.turbiditiesD[turb0]
|
for (turb0 in 0 until Skybox.turbCnt) {
|
||||||
println("....... Turbidity=$turbidity")
|
val turbidity = Skybox.turbiditiesD[turb0]
|
||||||
for (elev0 in 0 until Skybox.elevCnt) {
|
println("....... Turbidity=$turbidity")
|
||||||
val elevationDeg = Skybox.elevationsD[elev0]
|
for (elev0 in 0 until Skybox.elevCnt) {
|
||||||
val elevationRad = Math.toRadians(elevationDeg)
|
val elevationDeg = Skybox.elevationsD[elev0]
|
||||||
|
val elevationRad = Math.toRadians(elevationDeg)
|
||||||
// println("... Elevation: $elevationDeg")
|
// println("... Elevation: $elevationDeg")
|
||||||
|
|
||||||
val state = ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevationRad.abs())
|
val state =
|
||||||
|
ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevationRad.abs())
|
||||||
|
|
||||||
for (yp in 0 until Skybox.gradSize) {
|
for (yp in 0 until Skybox.gradSize) {
|
||||||
val yi = yp - 3
|
val yi = yp - 10
|
||||||
val xf = -elevationDeg / 90.0
|
val xf = -elevationDeg / 90.0
|
||||||
var yf = (yi / 58.0).coerceIn(0.0, 1.0).mapCircle().coerceInSmoothly(0.0, 0.95)
|
var yf = (yi / 58.0).coerceIn(0.0, 1.0).mapCircle().coerceInSmoothly(0.0, 0.95)
|
||||||
|
|
||||||
// experiments visualisation: https://www.desmos.com/calculator/5crifaekwa
|
// experiments visualisation: https://www.desmos.com/calculator/5crifaekwa
|
||||||
// if (elevationDeg < 0) yf *= 1.0 - pow(xf, 0.333)
|
// if (elevationDeg < 0) yf *= 1.0 - pow(xf, 0.333)
|
||||||
// if (elevationDeg < 0) yf *= -2.0 * asin(xf - 1.0) / PI
|
// if (elevationDeg < 0) yf *= -2.0 * asin(xf - 1.0) / PI
|
||||||
if (elevationDeg < 0) yf *= Skybox.superellipsoidDecay(1.0 / 3.0, xf)
|
if (elevationDeg < 0) yf *= Skybox.superellipsoidDecay(1.0 / 3.0, xf)
|
||||||
val theta = yf * HALF_PI
|
val theta = yf * HALF_PI
|
||||||
// vertical angle, where 0 is zenith, ±90 is ground (which is odd)
|
// vertical angle, where 0 is zenith, ±90 is ground (which is odd)
|
||||||
|
|
||||||
// println("$yp\t$theta")
|
// println("$yp\t$theta")
|
||||||
|
|
||||||
val xyz = CIEXYZ(
|
val xyz = CIEXYZ(
|
||||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 0).toFloat(),
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, (gammaPair * 2f + 1f) * HALF_PI, 0).toFloat(),
|
||||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 1).toFloat(),
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, (gammaPair * 2f + 1f) * HALF_PI, 1).toFloat(),
|
||||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 2).toFloat()
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, (gammaPair * 2f + 1f) * HALF_PI, 2).toFloat()
|
||||||
)
|
)
|
||||||
val xyz2 = xyz.scaleToFit(elevationDeg)
|
val xyz2 = xyz.scaleToFit(elevationDeg)
|
||||||
val rgb = xyz2.toRGB().toColor()
|
val rgb = xyz2.toRGB().toColor()
|
||||||
val colour = rgb.toIntBits().toLittle()
|
val colour = rgb.toIntBits().toLittle()
|
||||||
|
|
||||||
val imgOffX = (albedo0 * Skybox.elevCnt + elev0)
|
val imgOffX = albedo0 * Skybox.elevCnt + elev0 + Skybox.elevCnt * Skybox.albedoCnt * gammaPair
|
||||||
val imgOffY = texh - 1 - (Skybox.gradSize * turb0 + yp)
|
val imgOffY = texh - 1 - (Skybox.gradSize * turb0 + yp)
|
||||||
val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX)
|
val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX)
|
||||||
for (i in 0..3) {
|
for (i in 0..3) {
|
||||||
bytes[fileOffset + i] = colour[bytesLut[i]]
|
bytes[fileOffset + i] = colour[bytesLut[i]]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +96,7 @@ fun main() {
|
|||||||
|
|
||||||
println("Atlas generation done!")
|
println("Atlas generation done!")
|
||||||
|
|
||||||
File("./assets/mods/basegame/weathers/main_skybox.tga").writeBytes(bytes)
|
File("./assets/clut/skybox.tga").writeBytes(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val bytesLut = arrayOf(2,1,0,3,2,1,0,3) // For some reason BGRA order is what makes it work
|
private val bytesLut = arrayOf(2,1,0,3,2,1,0,3) // For some reason BGRA order is what makes it work
|
||||||
@@ -13,6 +13,8 @@ import net.torvald.parametricsky.ArHosekSkyModel
|
|||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.abs
|
import net.torvald.terrarum.abs
|
||||||
|
import net.torvald.terrarum.floorToInt
|
||||||
|
import net.torvald.terrarum.toInt
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
|
||||||
@@ -25,7 +27,7 @@ object Skybox : Disposable {
|
|||||||
private const val PI = 3.141592653589793
|
private const val PI = 3.141592653589793
|
||||||
private const val TWO_PI = 6.283185307179586
|
private const val TWO_PI = 6.283185307179586
|
||||||
|
|
||||||
const val gradSize = 64
|
const val gradSize = 78
|
||||||
|
|
||||||
private lateinit var gradTexBinLowAlbedo: Array<TextureRegion>
|
private lateinit var gradTexBinLowAlbedo: Array<TextureRegion>
|
||||||
private lateinit var gradTexBinHighAlbedo: Array<TextureRegion>
|
private lateinit var gradTexBinHighAlbedo: Array<TextureRegion>
|
||||||
@@ -37,6 +39,7 @@ object Skybox : Disposable {
|
|||||||
fun loadlut() {
|
fun loadlut() {
|
||||||
tex = Texture(Gdx.files.internal("assets/clut/skybox.png"))
|
tex = Texture(Gdx.files.internal("assets/clut/skybox.png"))
|
||||||
tex.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
tex.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||||
|
tex.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat)
|
||||||
texRegions = TextureRegionPack(tex, 2, gradSize - 2, 0, 2, 0, 1)
|
texRegions = TextureRegionPack(tex, 2, gradSize - 2, 0, 2, 0, 1)
|
||||||
texStripRegions = TextureRegionPack(tex, elevCnt, gradSize - 2, 0, 2, 0, 1)
|
texStripRegions = TextureRegionPack(tex, elevCnt, gradSize - 2, 0, 2, 0, 1)
|
||||||
}
|
}
|
||||||
@@ -50,28 +53,67 @@ object Skybox : Disposable {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
// use external LUT
|
// use external LUT
|
||||||
operator fun get(elevationDeg: Double, turbidity: Double, albedo: Double): TextureRegion {
|
operator fun get(elevationDeg: Double, turbidity: Double, albedo: Double, isAfternoon: Boolean): TextureRegion {
|
||||||
val elev = elevationDeg.coerceIn(-elevMax, elevMax).roundToInt().plus(elevMax).roundToInt()
|
TODO()
|
||||||
val turb = turbidity.coerceIn(1.0, 10.0).minus(1.0).times(turbDivisor).roundToInt()
|
|
||||||
val alb = albedo.coerceIn(0.1, 0.9).minus(0.1).times(turbDivisor).roundToInt()
|
|
||||||
//printdbg(this, "elev $elevationDeg->$elev; turb $turbidity->$turb; alb $albedo->$alb")
|
|
||||||
return texRegions.get(alb * elevCnt + elev, turb)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUV(elevationDeg: Double, turbidity: Double, albedo: Double): Pair<Texture, FloatArray> {
|
data class SkyboxRenderInfo(
|
||||||
val turb = turbidity.coerceIn(1.0, 10.0).minus(1.0).times(turbDivisor).roundToInt()
|
val texture: Texture,
|
||||||
val alb = albedo.coerceIn(0.1, 0.9).minus(0.1).times(turbDivisor).roundToInt()
|
val uvs: FloatArray,
|
||||||
val region = texStripRegions.get(alb, turb)
|
val turbidityPoint: Float,
|
||||||
|
val albedoPoint: Float,
|
||||||
|
)
|
||||||
|
|
||||||
val elev = elevationDeg.coerceIn(-elevMax, elevMax).plus(elevMax).div(elevations.last.toDouble()).div(albedoCnt).times((elevCnt - 1.0) / elevCnt)
|
fun getUV(elevationDeg: Double, turbidity: Double, albedo: Double): SkyboxRenderInfo {
|
||||||
|
val turb = turbidity.coerceIn(turbiditiesD.first(), turbiditiesD.last()).minus(1.0).times(turbDivisor)
|
||||||
|
val turbLo = turb.floorToInt()
|
||||||
|
val turbHi = min(turbCnt - 1, turbLo + 1)
|
||||||
|
val alb = albedo.coerceIn(albedos.first(), albedos.last()).times(5.0)
|
||||||
|
val albLo = alb.floorToInt()
|
||||||
|
val albHi = min(albedoCnt - 1, albLo + 1)
|
||||||
|
val elev = elevationDeg.coerceIn(-elevMax, elevMax).plus(elevMax).div(elevations.last.toDouble()).div(albedoCnt * 2).times((elevCnt - 1.0) / elevCnt)
|
||||||
|
|
||||||
val u = region.u + (0.5f / tex.width) + elev.toFloat() // because of the nature of bilinear interpolation, half pixels from the edges must be discarded
|
// A: morn, turbLow, albLow
|
||||||
|
// B: noon, turbLow, albLow
|
||||||
|
// C: morn, turbHigh, albLow
|
||||||
|
// D: noon, turbHigh, albLow
|
||||||
|
// E: morn, turbLow, albHigh
|
||||||
|
// F: noon, turbLow, albHigh
|
||||||
|
// G: morn, turbHigh, albHigh
|
||||||
|
// H: noon, turbHigh, albHigh
|
||||||
|
|
||||||
return tex to floatArrayOf(
|
val regionA = texStripRegions.get(albLo + albedoCnt * 0, turbLo)
|
||||||
u,
|
val regionB = texStripRegions.get(albLo + albedoCnt * 1, turbLo)
|
||||||
region.v,
|
val regionC = texStripRegions.get(albLo + albedoCnt * 0, turbHi)
|
||||||
u,
|
val regionD = texStripRegions.get(albLo + albedoCnt * 1, turbHi)
|
||||||
region.v2
|
val regionE = texStripRegions.get(albHi + albedoCnt * 0, turbLo)
|
||||||
|
val regionF = texStripRegions.get(albHi + albedoCnt * 1, turbLo)
|
||||||
|
val regionG = texStripRegions.get(albHi + albedoCnt * 0, turbHi)
|
||||||
|
val regionH = texStripRegions.get(albHi + albedoCnt * 1, turbHi)
|
||||||
|
// (0.5f / tex.width): because of the nature of bilinear interpolation, half pixels from the edges must be discarded
|
||||||
|
val uA = regionA.u + (0.5f / tex.width) + elev.toFloat()
|
||||||
|
val uB = regionB.u + (0.5f / tex.width) + elev.toFloat()
|
||||||
|
val uC = regionC.u + (0.5f / tex.width) + elev.toFloat()
|
||||||
|
val uD = regionD.u + (0.5f / tex.width) + elev.toFloat()
|
||||||
|
val uE = regionE.u + (0.5f / tex.width) + elev.toFloat()
|
||||||
|
val uF = regionF.u + (0.5f / tex.width) + elev.toFloat()
|
||||||
|
val uG = regionG.u + (0.5f / tex.width) + elev.toFloat()
|
||||||
|
val uH = regionH.u + (0.5f / tex.width) + elev.toFloat()
|
||||||
|
|
||||||
|
return SkyboxRenderInfo(
|
||||||
|
tex,
|
||||||
|
floatArrayOf(
|
||||||
|
uA, regionA.v, uA, regionA.v2,
|
||||||
|
uB, regionB.v, uB, regionB.v2,
|
||||||
|
uC, regionC.v, uC, regionC.v2,
|
||||||
|
uD, regionD.v, uD, regionD.v2,
|
||||||
|
uE, regionE.v, uE, regionE.v2,
|
||||||
|
uF, regionF.v, uF, regionF.v2,
|
||||||
|
uG, regionG.v, uG, regionG.v2,
|
||||||
|
uH, regionH.v, uH, regionH.v2,
|
||||||
|
),
|
||||||
|
(turb - turbLo).toFloat(),
|
||||||
|
(alb - albLo).toFloat(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,15 +130,20 @@ object Skybox : Disposable {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val deg1 = (-elevationDeg / elevMax).pow(0.93).times(-elevMax)
|
// maths model: https://www.desmos.com/calculator/cwi7iyzygg
|
||||||
val elevation1 = -deg1
|
|
||||||
val elevation2 = -deg1 / 28.5
|
val x = -elevationDeg.toFloat()
|
||||||
val scale = (1f - (1f - 1f / 1.8.pow(elevation1)) * 0.97f).toFloat()
|
// val elevation2 = elevationDeg.toFloat() / 28.5f
|
||||||
val scale2 = (1.0 - (elevation2.pow(E) / E.pow(elevation2))*0.8).toFloat()
|
val p = 3.5f
|
||||||
|
val q = 7.5f
|
||||||
|
val s = -0.2f
|
||||||
|
val f = (1f - (1f - 1f / 1.8f.pow(x)) * 0.97f).toFloat()
|
||||||
|
// val g = (1.0 - (elevation2.pow(E) / E.pow(elevation2))*0.8).toFloat()
|
||||||
|
val h = ((x / q).pow(p) + 1f).pow(s)
|
||||||
CIEXYZ(
|
CIEXYZ(
|
||||||
this.X.scaleFun() * scale * scale2,
|
this.X.scaleFun() * f * h,
|
||||||
this.Y.scaleFun() * scale * scale2,
|
this.Y.scaleFun() * f * h,
|
||||||
this.Z.scaleFun() * scale * scale2,
|
this.Z.scaleFun() * f * h,
|
||||||
this.alpha
|
this.alpha
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -105,15 +152,13 @@ object Skybox : Disposable {
|
|||||||
val elevations = (0..150)
|
val elevations = (0..150)
|
||||||
val elevMax = elevations.last / 2.0
|
val elevMax = elevations.last / 2.0
|
||||||
val elevationsD = elevations.map { -elevMax + it } // -75, -74, -73, ..., 74, 75 // (specifically using whole number of angles because angle units any finer than 1.0 would make "hack" sunsut happen too fast)
|
val elevationsD = elevations.map { -elevMax + it } // -75, -74, -73, ..., 74, 75 // (specifically using whole number of angles because angle units any finer than 1.0 would make "hack" sunsut happen too fast)
|
||||||
val turbidities = (0..45) // 1, 1.2, 1.4, 1.6, ..., 10.0
|
val turbidities = (0..25) // 1, 1.2, 1.4, 1.6, ..., 6.0
|
||||||
val turbDivisor = 5.0
|
val turbDivisor = 5.0
|
||||||
val turbiditiesD = turbidities.map { 1.0 + it / turbDivisor }
|
val turbiditiesD = turbidities.map { 1.0 + it / turbDivisor }
|
||||||
val albedos = arrayOf(0.1, 0.3, 0.5, 0.7, 0.9)
|
val albedos = arrayOf(0.0, 0.2, 0.4, 0.6, 0.8, 1.0)
|
||||||
val elevCnt = elevations.count()
|
val elevCnt = elevations.count()
|
||||||
val turbCnt = turbidities.count()
|
val turbCnt = turbidities.count()
|
||||||
val albedoCnt = albedos.size
|
val albedoCnt = albedos.size
|
||||||
val albedoLow = 0.1
|
|
||||||
val albedoHight = 0.8 // for theoretical "winter wonderland"?
|
|
||||||
val gamma = HALF_PI
|
val gamma = HALF_PI
|
||||||
|
|
||||||
internal fun Double.mapCircle() = sin(HALF_PI * this)
|
internal fun Double.mapCircle() = sin(HALF_PI * this)
|
||||||
@@ -121,8 +166,7 @@ object Skybox : Disposable {
|
|||||||
internal fun initiate() {
|
internal fun initiate() {
|
||||||
printdbg(this, "Initialising skybox model")
|
printdbg(this, "Initialising skybox model")
|
||||||
|
|
||||||
gradTexBinLowAlbedo = getTexturmaps(albedoLow)
|
TODO()
|
||||||
gradTexBinHighAlbedo = getTexturmaps(albedoHight)
|
|
||||||
|
|
||||||
App.disposables.add(this)
|
App.disposables.add(this)
|
||||||
|
|
||||||
@@ -170,6 +214,11 @@ object Skybox : Disposable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* To get the idea what the fuck is going on here, please refer to https://www.desmos.com/calculator/snqglcu2wl
|
* To get the idea what the fuck is going on here, please refer to https://www.desmos.com/calculator/snqglcu2wl
|
||||||
|
*
|
||||||
|
* Sidenote: the original model involved two cosine curves, but since its Taylor series begins with x^2, I figured
|
||||||
|
* quadratic curve ought to be good enough, and the error against the original model was below 1/255 for
|
||||||
|
* reasonable range of p, and that's the reason I stopped at x^2 rather than also taking x^4 into the approximated
|
||||||
|
* model that is the code below.
|
||||||
*/
|
*/
|
||||||
internal fun smoothLinear(p: Double, x0: Double): Double {
|
internal fun smoothLinear(p: Double, x0: Double): Double {
|
||||||
val x = x0 - 0.5
|
val x = x0 - 0.5
|
||||||
@@ -198,7 +247,7 @@ object Skybox : Disposable {
|
|||||||
// printdbg(this, "elev $elevationDeg turb $turbidity")
|
// printdbg(this, "elev $elevationDeg turb $turbidity")
|
||||||
|
|
||||||
for (yp in 0 until gradSize) {
|
for (yp in 0 until gradSize) {
|
||||||
val yi = yp - 3
|
val yi = yp - 10
|
||||||
val xf = -elevationDeg / 90.0
|
val xf = -elevationDeg / 90.0
|
||||||
var yf = (yi / 58.0).coerceIn(0.0, 1.0).mapCircle().coerceInSmoothly(0.0, 0.95)
|
var yf = (yi / 58.0).coerceIn(0.0, 1.0).mapCircle().coerceInSmoothly(0.0, 0.95)
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ internal object Authenticator : ConsoleCommand {
|
|||||||
println("auth passwd: '$pwd'")
|
println("auth passwd: '$pwd'")
|
||||||
println("hash: $hashedPwd")
|
println("hash: $hashedPwd")
|
||||||
|
|
||||||
if ("09ccf5067db6f58265b004829e33e715e819ba0984f1e1fcef49c36fcd5f745f".equals(hashedPwd, ignoreCase = true)) {
|
if ("2d962f949f55906ac47f16095ded190c9e44d95920259b8f36c2e54bd75df173".equals(hashedPwd, ignoreCase = true)) {
|
||||||
// beedle
|
// beedle
|
||||||
val msg = if (a) "Locked" else "Authenticated"
|
val msg = if (a) "Locked" else "Authenticated"
|
||||||
Echo(msg)
|
Echo(msg)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -145,6 +145,9 @@ class Hitbox {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize the hitbox centred around the "canonical" point.
|
||||||
|
*/
|
||||||
fun canonicalResize(w: Double, h: Double): Hitbox {
|
fun canonicalResize(w: Double, h: Double): Hitbox {
|
||||||
// sx_1 + 0.5w_1 = sx_2 + 0.5w_2 // equals because the final point must not move. sx_1: old start-x, sx_2: new start-x which is what we want
|
// sx_1 + 0.5w_1 = sx_2 + 0.5w_2 // equals because the final point must not move. sx_1: old start-x, sx_2: new start-x which is what we want
|
||||||
// sx_2 = sx_1 + 0.5w_1 - 0.5w_2 // move variables to right-hand side to derive final value sx_2
|
// sx_2 = sx_1 + 0.5w_1 - 0.5w_2 // move variables to right-hand side to derive final value sx_2
|
||||||
|
|||||||
@@ -5,14 +5,11 @@ import com.badlogic.gdx.Input
|
|||||||
import com.badlogic.gdx.InputAdapter
|
import com.badlogic.gdx.InputAdapter
|
||||||
import com.badlogic.gdx.controllers.Controllers
|
import com.badlogic.gdx.controllers.Controllers
|
||||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.App.printdbgerr
|
import net.torvald.terrarum.App.printdbgerr
|
||||||
import net.torvald.terrarum.ItemCodex
|
|
||||||
import net.torvald.terrarum.Terrarum
|
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
import net.torvald.terrarum.controller.TerrarumController
|
import net.torvald.terrarum.controller.TerrarumController
|
||||||
import net.torvald.terrarum.floorToInt
|
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
import net.torvald.terrarum.gameitems.GameItem
|
import net.torvald.terrarum.gameitems.GameItem
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
@@ -168,7 +165,7 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
|
|||||||
|
|
||||||
// pie menu
|
// pie menu
|
||||||
if (App.getConfigIntArray("control_key_quickselalt").contains(keycode)
|
if (App.getConfigIntArray("control_key_quickselalt").contains(keycode)
|
||||||
|| keycode == App.getConfigInt("control_key_quicksel")) {
|
|| keycode == ControlPresets.getKey("control_key_quicksel")) {
|
||||||
terrarumIngame.uiPieMenu.setAsOpen()
|
terrarumIngame.uiPieMenu.setAsOpen()
|
||||||
terrarumIngame.uiQuickBar.setAsClose()
|
terrarumIngame.uiQuickBar.setAsClose()
|
||||||
}
|
}
|
||||||
@@ -194,7 +191,7 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
|
|||||||
|
|
||||||
private fun tKeyUp(keycode: Int): Boolean {
|
private fun tKeyUp(keycode: Int): Boolean {
|
||||||
if (App.getConfigIntArray("control_key_quickselalt").contains(keycode)
|
if (App.getConfigIntArray("control_key_quickselalt").contains(keycode)
|
||||||
|| keycode == App.getConfigInt("control_key_quicksel")) {
|
|| keycode == ControlPresets.getKey("control_key_quicksel")) {
|
||||||
terrarumIngame.uiPieMenu.setAsClose()
|
terrarumIngame.uiPieMenu.setAsClose()
|
||||||
terrarumIngame.uiQuickBar.setAsOpen()
|
terrarumIngame.uiQuickBar.setAsOpen()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -359,6 +359,8 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun hasTag(s: String) = tags.contains(s)
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.TWO_PI
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.sin
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,8 +56,10 @@ import kotlin.math.sin
|
|||||||
*/
|
*/
|
||||||
class WorldTime(initTime: Long = 0L) {
|
class WorldTime(initTime: Long = 0L) {
|
||||||
|
|
||||||
|
@Transient private val TWO_PI = Math.PI * 2.0
|
||||||
|
|
||||||
/** It is not recommended to directly modify the TIME_T. Use provided methods instead. */
|
/** It is not recommended to directly modify the TIME_T. Use provided methods instead. */
|
||||||
var TIME_T = 0L // Epoch: Year 125 Spring 1st, 0h00:00 (Mondag) // 125-01-01
|
var TIME_T = 0L // Epoch: Year 1 Spring 1st, 0h00:00 (Mondag) // 0001-01-01
|
||||||
|
|
||||||
init {
|
init {
|
||||||
TIME_T = initTime
|
TIME_T = initTime
|
||||||
@@ -151,21 +152,7 @@ class WorldTime(initTime: Long = 0L) {
|
|||||||
@Transient private val REAL_SEC_TO_GAME_SECS = 1.0 / GAME_MIN_TO_REAL_SEC // how slow is real-life clock (second-wise) relative to the ingame one
|
@Transient private val REAL_SEC_TO_GAME_SECS = 1.0 / GAME_MIN_TO_REAL_SEC // how slow is real-life clock (second-wise) relative to the ingame one
|
||||||
|
|
||||||
// NOTE: ingame calendars (the fixture with GUI) should use symbols AND fullnames; the watch already uses shot daynames
|
// NOTE: ingame calendars (the fixture with GUI) should use symbols AND fullnames; the watch already uses shot daynames
|
||||||
val DAY_NAMES = arrayOf(//daynames are taken from Nynorsk (å -> o)
|
|
||||||
"Mondag", "Tysdag", "Midtveke" //middle-week
|
|
||||||
, "Torsdag", "Fredag", "Laurdag", "Sundag", "Verddag" //From Norsk word 'verd'
|
|
||||||
)
|
|
||||||
val DAY_NAMES_SHORT = arrayOf("Mon", "Tys", "Mid", "Tor", "Fre", "Lau", "Sun", "Ver")
|
|
||||||
|
|
||||||
// dwarven calendar of 12 monthes
|
|
||||||
/*val MONTH_NAMES = arrayOf(
|
|
||||||
"Opal", "Obsidian", "Granite", "Slate", "Felsite", "Hematite",
|
|
||||||
"Malachite", "Galena", "Limestone", "Sandstone", "Timber", "Moonstone"
|
|
||||||
)
|
|
||||||
val MONTH_NAMES_SHORT = arrayOf("Opal", "Obsi", "Gran", "Slat", "Fels", "Hema",
|
|
||||||
"Mala", "Gale", "Lime", "Sand", "Timb", "Moon")*/
|
|
||||||
val MONTH_NAMES = arrayOf("Spring", "Summer", "Autumn", "Winter")
|
|
||||||
val MONTH_NAMES_SHORT = arrayOf("Spri", "Summ", "Autm", "Wint")
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** Each day is displayed as 24 hours, but in real-life clock it's 22 mins long */
|
/** Each day is displayed as 24 hours, but in real-life clock it's 22 mins long */
|
||||||
@@ -181,7 +168,7 @@ class WorldTime(initTime: Long = 0L) {
|
|||||||
|
|
||||||
const val MONTH_LENGTH = 30 // ingame calendar specific
|
const val MONTH_LENGTH = 30 // ingame calendar specific
|
||||||
|
|
||||||
const val EPOCH_YEAR = 125
|
const val EPOCH_YEAR = 1
|
||||||
|
|
||||||
val YEAR_SECONDS = DAY_LENGTH * YEAR_DAYS
|
val YEAR_SECONDS = DAY_LENGTH * YEAR_DAYS
|
||||||
|
|
||||||
@@ -203,6 +190,31 @@ class WorldTime(initTime: Long = 0L) {
|
|||||||
|
|
||||||
val LUNAR_CYCLE: Int = 29 * DAY_LENGTH + 12 * HOUR_SEC + 44 * MINUTE_SEC + 3 // 29 days, 12 hours, 44 minutes, and 3 seconds in-game calendar
|
val LUNAR_CYCLE: Int = 29 * DAY_LENGTH + 12 * HOUR_SEC + 44 * MINUTE_SEC + 3 // 29 days, 12 hours, 44 minutes, and 3 seconds in-game calendar
|
||||||
const val DIURNAL_MOTION_LENGTH = 86636f
|
const val DIURNAL_MOTION_LENGTH = 86636f
|
||||||
|
|
||||||
|
val DAY_NAMES = arrayOf(//daynames are taken from Nynorsk (å -> o)
|
||||||
|
"MONDAG", "TYSDAG", "MIDTVEKE" //middle-week
|
||||||
|
, "TORSDAG", "FREDAG", "LAURDAG", "SUNDAG", "VERDDAG" //From Norsk word 'verd'
|
||||||
|
)
|
||||||
|
val DAY_NAMES_SHORT = arrayOf("MON", "TYS", "MID", "TOR", "FRE", "LAU", "SUN", "VER")
|
||||||
|
// dwarven calendar of 12 monthes
|
||||||
|
/*val MONTH_NAMES = arrayOf(
|
||||||
|
"Opal", "Obsidian", "Granite", "Slate", "Felsite", "Hematite",
|
||||||
|
"Malachite", "Galena", "Limestone", "Sandstone", "Timber", "Moonstone"
|
||||||
|
)
|
||||||
|
val MONTH_NAMES_SHORT = arrayOf("Opal", "Obsi", "Gran", "Slat", "Fels", "Hema",
|
||||||
|
"Mala", "Gale", "Lime", "Sand", "Timb", "Moon")*/
|
||||||
|
val MONTH_NAMES = arrayOf("SPRING", "SUMMER", "AUTUMN", "WINTER")
|
||||||
|
val MONTH_NAMES_SHORT = arrayOf("SPRI", "SUMM", "AUTM", "WINT")
|
||||||
|
|
||||||
|
val DAY_NAMES_LANG_KEYS = DAY_NAMES.map { "CONTEXT_CALENDAR_DAY_${it}_DNT" }
|
||||||
|
val DAY_NAMES_SHORT_LANG_KEYS = DAY_NAMES_SHORT.map { "CONTEXT_CALENDAR_DAY_${it}_DNT" }
|
||||||
|
val MONTH_NAMES_LANG_KEYS = MONTH_NAMES.map { "CONTEXT_CALENDAR_SEASON_${it}" }
|
||||||
|
val MONTH_NAMES_SHORT_LANG_KEYS = MONTH_NAMES_SHORT.map { "CONTEXT_CALENDAR_SEASON_${it}" }
|
||||||
|
|
||||||
|
fun getDayName(index: Int) = Lang[DAY_NAMES_LANG_KEYS[index]]
|
||||||
|
fun getDayNameShort(index: Int) = Lang[DAY_NAMES_SHORT_LANG_KEYS[index]]
|
||||||
|
fun getMonthName(index: Int) = Lang[MONTH_NAMES_LANG_KEYS[index - 1]]
|
||||||
|
fun getMonthNameShort(index: Int) = Lang[MONTH_NAMES_SHORT_LANG_KEYS[index - 1]]
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(delta: Float) {
|
fun update(delta: Float) {
|
||||||
@@ -228,27 +240,30 @@ class WorldTime(initTime: Long = 0L) {
|
|||||||
TIME_T += t
|
TIME_T += t
|
||||||
}
|
}
|
||||||
|
|
||||||
val dayName: String
|
|
||||||
get() = DAY_NAMES[dayOfWeek]
|
|
||||||
|
|
||||||
fun Long.toPositiveInt() = this.and(0x7FFFFFFF).toInt()
|
fun Long.toPositiveInt() = this.and(0x7FFFFFFF).toInt()
|
||||||
fun Long.abs() = Math.abs(this)
|
fun Long.abs() = Math.abs(this)
|
||||||
|
|
||||||
/** Format: "%A, %Y %B %d %X" */
|
/** Format: "ɣ%Y %B %d %A, %X" */
|
||||||
fun getFormattedTime() = "${getDayNameShort()}, " +
|
fun getFormattedTime() =
|
||||||
"$years " +
|
"ɣ$years " +
|
||||||
"${getMonthNameFull()} " +
|
"${getMonthNameFull()} " +
|
||||||
"$calendarDay " +
|
"$calendarDay " +
|
||||||
"${String.format("%02d", hours)}:" +
|
"${getDayNameFull()}, " +
|
||||||
"${String.format("%02d", minutes)}:" +
|
"${String.format("%02d", hours)}:" +
|
||||||
"${String.format("%02d", seconds)}"
|
"${String.format("%02d", minutes)}:" +
|
||||||
|
"${String.format("%02d", seconds)}"
|
||||||
|
fun getFormattedCalendarDay() =
|
||||||
|
"ɣ$years " +
|
||||||
|
"${getMonthNameFull()} " +
|
||||||
|
"$calendarDay " +
|
||||||
|
"${getDayNameFull()}"
|
||||||
fun getShortTime() = "${years.toString().padStart(4, '0')}-${getMonthNameShort()}-${calendarDay.toString().padStart(2, '0')}"
|
fun getShortTime() = "${years.toString().padStart(4, '0')}-${getMonthNameShort()}-${calendarDay.toString().padStart(2, '0')}"
|
||||||
fun getFilenameTime() = "${years.toString().padStart(4, '0')}${calendarMonth.toString().padStart(2, '0')}${calendarDay.toString().padStart(2, '0')}"
|
fun getFilenameTime() = "${years.toString().padStart(4, '0')}${calendarMonth.toString().padStart(2, '0')}${calendarDay.toString().padStart(2, '0')}"
|
||||||
|
|
||||||
fun getDayNameFull() = DAY_NAMES[dayOfWeek]
|
fun getDayNameFull() = getDayName(dayOfWeek)
|
||||||
fun getDayNameShort() = DAY_NAMES_SHORT[dayOfWeek]
|
fun getDayNameShort() = getDayNameShort(dayOfWeek)
|
||||||
fun getMonthNameFull() = MONTH_NAMES[calendarMonth - 1]
|
fun getMonthNameFull() = getMonthName(calendarMonth)
|
||||||
fun getMonthNameShort() = MONTH_NAMES_SHORT[calendarMonth - 1]
|
fun getMonthNameShort() = getMonthNameShort(calendarMonth)
|
||||||
|
|
||||||
override fun toString() = getFormattedTime()
|
override fun toString() = getFormattedTime()
|
||||||
}
|
}
|
||||||
@@ -152,6 +152,15 @@ object Lang {
|
|||||||
return sb.toString()
|
return sb.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getAndUseTemplate(key: String, capitalise: Boolean = true, vararg arguments: Any?): String {
|
||||||
|
var raw = get(key, capitalise)
|
||||||
|
arguments.forEachIndexed { index, it0 ->
|
||||||
|
val it = if (capitalise) it0.toString().capitalize() else it0.toString()
|
||||||
|
raw = raw.replace("{${index}}", it)
|
||||||
|
}
|
||||||
|
return raw
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does NOT parse the operators
|
* Does NOT parse the operators
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
|
|
||||||
IngameRenderer.setRenderedWorld(gameWorld)
|
IngameRenderer.setRenderedWorld(gameWorld)
|
||||||
|
WeatherMixer.internalReset()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.badlogic.gdx.Input
|
import com.badlogic.gdx.Input
|
||||||
import com.badlogic.gdx.graphics.*
|
import com.badlogic.gdx.graphics.*
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import com.badlogic.gdx.graphics.glutils.FloatFrameBuffer
|
import com.badlogic.gdx.graphics.glutils.Float16FrameBuffer
|
||||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.App.*
|
import net.torvald.terrarum.App.*
|
||||||
@@ -53,20 +52,20 @@ object IngameRenderer : Disposable {
|
|||||||
private lateinit var blurWriteQuad2: Mesh
|
private lateinit var blurWriteQuad2: Mesh
|
||||||
// private lateinit var blurWriteQuad4: Mesh
|
// private lateinit var blurWriteQuad4: Mesh
|
||||||
|
|
||||||
private lateinit var lightmapFbo: FloatFrameBuffer
|
private lateinit var lightmapFbo: Float16FrameBuffer
|
||||||
private lateinit var fboRGB: FloatFrameBuffer
|
private lateinit var fboRGB: Float16FrameBuffer
|
||||||
private lateinit var fboRGB_lightMixed: FloatFrameBuffer
|
private lateinit var fboRGB_lightMixed: Float16FrameBuffer
|
||||||
private lateinit var fboA: FloatFrameBuffer
|
private lateinit var fboA: Float16FrameBuffer
|
||||||
private lateinit var fboA_lightMixed: FloatFrameBuffer
|
private lateinit var fboA_lightMixed: Float16FrameBuffer
|
||||||
private lateinit var fboMixedOut: FloatFrameBuffer
|
private lateinit var fboMixedOut: Float16FrameBuffer
|
||||||
private lateinit var rgbTex: TextureRegion
|
private lateinit var rgbTex: TextureRegion
|
||||||
private lateinit var aTex: TextureRegion
|
private lateinit var aTex: TextureRegion
|
||||||
private lateinit var mixedOutTex: TextureRegion
|
private lateinit var mixedOutTex: TextureRegion
|
||||||
private lateinit var lightTex: TextureRegion
|
private lateinit var lightTex: TextureRegion
|
||||||
private lateinit var blurTex: TextureRegion
|
private lateinit var blurTex: TextureRegion
|
||||||
|
|
||||||
private lateinit var fboBlurHalf: FloatFrameBuffer
|
private lateinit var fboBlurHalf: Float16FrameBuffer
|
||||||
// private lateinit var fboBlurQuarter: FloatFrameBuffer
|
// private lateinit var fboBlurQuarter: Float16FrameBuffer
|
||||||
|
|
||||||
// you must have lightMixed FBO; otherwise you'll be reading from unbaked FBO and it freaks out GPU
|
// you must have lightMixed FBO; otherwise you'll be reading from unbaked FBO and it freaks out GPU
|
||||||
|
|
||||||
@@ -256,7 +255,9 @@ object IngameRenderer : Disposable {
|
|||||||
gdxClearAndEnableBlend(0f, 0f, 0f, 0f)
|
gdxClearAndEnableBlend(0f, 0f, 0f, 0f)
|
||||||
|
|
||||||
// draw sky
|
// draw sky
|
||||||
WeatherMixer.render(camera, batch, world)
|
measureDebugTime("WeatherMixer.render") {
|
||||||
|
WeatherMixer.render(camera, batch, world)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// normal behaviour
|
// normal behaviour
|
||||||
@@ -694,7 +695,7 @@ object IngameRenderer : Disposable {
|
|||||||
|
|
||||||
private const val KAWASE_POWER = 1.5f
|
private const val KAWASE_POWER = 1.5f
|
||||||
|
|
||||||
fun processNoBlur(outFbo: FloatFrameBuffer) {
|
fun processNoBlur(outFbo: Float16FrameBuffer) {
|
||||||
|
|
||||||
blurtex0.dispose()
|
blurtex0.dispose()
|
||||||
|
|
||||||
@@ -710,7 +711,7 @@ object IngameRenderer : Disposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun processKawaseBlur(outFbo: FloatFrameBuffer) {
|
fun processKawaseBlur(outFbo: Float16FrameBuffer) {
|
||||||
|
|
||||||
blurtex0.dispose()
|
blurtex0.dispose()
|
||||||
|
|
||||||
@@ -807,12 +808,12 @@ object IngameRenderer : Disposable {
|
|||||||
//fboBlurQuarter.dispose()
|
//fboBlurQuarter.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
fboRGB = FloatFrameBuffer(width, height, false)
|
fboRGB = Float16FrameBuffer(width, height, false)
|
||||||
fboRGB_lightMixed = FloatFrameBuffer(width, height, false)
|
fboRGB_lightMixed = Float16FrameBuffer(width, height, false)
|
||||||
fboA = FloatFrameBuffer(width, height, false)
|
fboA = Float16FrameBuffer(width, height, false)
|
||||||
fboA_lightMixed = FloatFrameBuffer(width, height, false)
|
fboA_lightMixed = Float16FrameBuffer(width, height, false)
|
||||||
fboMixedOut = FloatFrameBuffer(width, height, false)
|
fboMixedOut = Float16FrameBuffer(width, height, false)
|
||||||
lightmapFbo = FloatFrameBuffer(
|
lightmapFbo = Float16FrameBuffer(
|
||||||
LightmapRenderer.lightBuffer.width * LightmapRenderer.DRAW_TILE_SIZE.toInt(),
|
LightmapRenderer.lightBuffer.width * LightmapRenderer.DRAW_TILE_SIZE.toInt(),
|
||||||
LightmapRenderer.lightBuffer.height * LightmapRenderer.DRAW_TILE_SIZE.toInt(),
|
LightmapRenderer.lightBuffer.height * LightmapRenderer.DRAW_TILE_SIZE.toInt(),
|
||||||
false
|
false
|
||||||
@@ -823,13 +824,13 @@ object IngameRenderer : Disposable {
|
|||||||
blurTex = TextureRegion()
|
blurTex = TextureRegion()
|
||||||
mixedOutTex = TextureRegion(fboMixedOut.colorBufferTexture)
|
mixedOutTex = TextureRegion(fboMixedOut.colorBufferTexture)
|
||||||
|
|
||||||
fboBlurHalf = FloatFrameBuffer(
|
fboBlurHalf = Float16FrameBuffer(
|
||||||
LightmapRenderer.lightBuffer.width * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 2,
|
LightmapRenderer.lightBuffer.width * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 2,
|
||||||
LightmapRenderer.lightBuffer.height * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 2,
|
LightmapRenderer.lightBuffer.height * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 2,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
|
||||||
/*fboBlurQuarter = FloatFrameBuffer(
|
/*fboBlurQuarter = Float16FrameBuffer(
|
||||||
LightmapRenderer.lightBuffer.width * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 4,
|
LightmapRenderer.lightBuffer.width * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 4,
|
||||||
LightmapRenderer.lightBuffer.height * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 4,
|
LightmapRenderer.lightBuffer.height * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 4,
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import com.badlogic.gdx.graphics.OrthographicCamera
|
|||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import com.badlogic.gdx.graphics.glutils.FloatFrameBuffer
|
import com.badlogic.gdx.graphics.glutils.Float16FrameBuffer
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
@@ -147,7 +147,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
internal lateinit var uiRemoCon: UIRemoCon
|
internal lateinit var uiRemoCon: UIRemoCon
|
||||||
internal lateinit var uiFakeBlurOverlay: UICanvas
|
internal lateinit var uiFakeBlurOverlay: UICanvas
|
||||||
|
|
||||||
private lateinit var worldFBO: FloatFrameBuffer
|
private lateinit var worldFBO: Float16FrameBuffer
|
||||||
|
|
||||||
private val warning32bitJavaIcon = TextureRegion(Texture(Gdx.files.internal("assets/graphics/gui/32_bit_warning.tga")))
|
private val warning32bitJavaIcon = TextureRegion(Texture(Gdx.files.internal("assets/graphics/gui/32_bit_warning.tga")))
|
||||||
private val warningAppleRosettaIcon = TextureRegion(Texture(Gdx.files.internal("assets/graphics/gui/apple_rosetta_warning.tga")))
|
private val warningAppleRosettaIcon = TextureRegion(Texture(Gdx.files.internal("assets/graphics/gui/apple_rosetta_warning.tga")))
|
||||||
@@ -166,12 +166,12 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
||||||
val world = ReadSimpleWorld(reader, file)
|
val world = ReadSimpleWorld(reader, file)
|
||||||
demoWorld = world
|
demoWorld = world
|
||||||
demoWorld.worldTime.timeDelta = 330 // a year = 8 minutes
|
demoWorld.worldTime.timeDelta = 30
|
||||||
printdbg(this, "Demo world loaded")
|
printdbg(this, "Demo world loaded")
|
||||||
}
|
}
|
||||||
catch (e: IOException) {
|
catch (e: IOException) {
|
||||||
demoWorld = GameWorld(LandUtil.CHUNK_W, LandUtil.CHUNK_H, 0L, 0L)
|
demoWorld = GameWorld(LandUtil.CHUNK_W, LandUtil.CHUNK_H, 0L, 0L)
|
||||||
demoWorld.worldTime.timeDelta = 60
|
demoWorld.worldTime.timeDelta = 30
|
||||||
printdbg(this, "Demo world not found, using empty world")
|
printdbg(this, "Demo world not found, using empty world")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,6 +210,8 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
|
|
||||||
IngameRenderer.setRenderedWorld(demoWorld)
|
IngameRenderer.setRenderedWorld(demoWorld)
|
||||||
|
WeatherMixer.internalReset()
|
||||||
|
WeatherMixer.titleScreenInitWeather()
|
||||||
|
|
||||||
|
|
||||||
// load a half-gradient texture that would be used throughout the titlescreen and its sub UIs
|
// load a half-gradient texture that would be used throughout the titlescreen and its sub UIs
|
||||||
@@ -262,7 +264,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
Gdx.input.inputProcessor = TitleScreenController(this)
|
Gdx.input.inputProcessor = TitleScreenController(this)
|
||||||
|
|
||||||
|
|
||||||
worldFBO = FloatFrameBuffer(App.scr.width, App.scr.height, false)
|
worldFBO = Float16FrameBuffer(App.scr.width, App.scr.height, false)
|
||||||
|
|
||||||
// load list of savegames
|
// load list of savegames
|
||||||
printdbg(this, "update list of savegames")
|
printdbg(this, "update list of savegames")
|
||||||
@@ -285,20 +287,15 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val updateScreen = { delta: Float ->
|
private val updateScreen = { delta: Float ->
|
||||||
// TODO: desynched weather and time-of-day change
|
|
||||||
|
|
||||||
val forcedTime = 32880 // 9h08m
|
|
||||||
demoWorld.globalLight = WeatherMixer.globalLightNow
|
demoWorld.globalLight = WeatherMixer.globalLightNow
|
||||||
// demoWorld.globalLight = WeatherMixer.getGlobalLightOfTimeOfNoon()
|
|
||||||
demoWorld.updateWorldTime(delta)
|
demoWorld.updateWorldTime(delta)
|
||||||
// WeatherMixer.update(delta, cameraPlayer, demoWorld)
|
WeatherMixer.update(delta, cameraPlayer, demoWorld)
|
||||||
WeatherMixer.forceTimeAt = forcedTime
|
|
||||||
cameraPlayer.update(delta)
|
cameraPlayer.update(delta)
|
||||||
|
|
||||||
// worldcamera update AFTER cameraplayer in this case; the other way is just an exception for actual ingame SFX
|
// worldcamera update AFTER cameraplayer in this case; the other way is just an exception for actual ingame SFX
|
||||||
WorldCamera.update(demoWorld, cameraPlayer)
|
WorldCamera.update(demoWorld, cameraPlayer)
|
||||||
|
|
||||||
|
|
||||||
// update UIs //
|
// update UIs //
|
||||||
uiContainer.forEach { it?.update(delta) }
|
uiContainer.forEach { it?.update(delta) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,16 +14,21 @@ import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
|||||||
*/
|
*/
|
||||||
internal object Inventory : ConsoleCommand {
|
internal object Inventory : ConsoleCommand {
|
||||||
|
|
||||||
private var targetID: ActorID = INGAME.actorNowPlaying?.referenceID ?: PLAYER_REF_ID
|
private var targetID: ActorID = 0
|
||||||
|
|
||||||
|
private fun tryTargetActivePlayer() {
|
||||||
|
targetID = INGAME.actorNowPlaying?.referenceID ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
override fun execute(args: Array<String>) {
|
override fun execute(args: Array<String>) {
|
||||||
if (args.size == 1) {
|
if (args.size == 1) {
|
||||||
printUsage()
|
printUsage()
|
||||||
}
|
}
|
||||||
else if (args[1] == "target") {
|
else if (args[1] == "target") {
|
||||||
targetID = if (args[2].lowercase() == "player") (INGAME.actorNowPlaying?.referenceID ?: PLAYER_REF_ID) else args[2].toInt()
|
if (args[2].lowercase() == "player") tryTargetActivePlayer() else targetID = args[2].toInt()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (targetID == 0) tryTargetActivePlayer()
|
||||||
val actor = getActor()
|
val actor = getActor()
|
||||||
if (actor != null) {
|
if (actor != null) {
|
||||||
when (args[1]) {
|
when (args[1]) {
|
||||||
@@ -36,7 +41,7 @@ internal object Inventory : ConsoleCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Echo("Actor $targetID is not Pocketed or does not exists")
|
Echo("Actor $targetID is not Pocketed or does not exist")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/net/torvald/terrarum/modulebasegame/console/Uuid.kt
Normal file
22
src/net/torvald/terrarum/modulebasegame/console/Uuid.kt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.console
|
||||||
|
|
||||||
|
import net.torvald.terrarum.INGAME
|
||||||
|
import net.torvald.terrarum.ccG
|
||||||
|
import net.torvald.terrarum.ccY
|
||||||
|
import net.torvald.terrarum.console.ConsoleCommand
|
||||||
|
import net.torvald.terrarum.console.Echo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-22.
|
||||||
|
*/
|
||||||
|
object Uuid : ConsoleCommand {
|
||||||
|
override fun execute(args: Array<String>) {
|
||||||
|
val worldUUID = INGAME.world.worldIndex
|
||||||
|
val playerUUID = INGAME.actorGamer.uuid
|
||||||
|
Echo("${ccY}World UUID: ${ccG}$worldUUID")
|
||||||
|
Echo("${ccY}Player UUID: ${ccG}$playerUUID")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun printUsage() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,6 @@ import net.torvald.terrarum.App.printdbg
|
|||||||
import net.torvald.terrarum.gameactors.*
|
import net.torvald.terrarum.gameactors.*
|
||||||
import net.torvald.terrarum.gameactors.faction.Faction
|
import net.torvald.terrarum.gameactors.faction.Faction
|
||||||
import net.torvald.terrarum.gameitems.GameItem
|
import net.torvald.terrarum.gameitems.GameItem
|
||||||
import net.torvald.terrarum.itemproperties.Material
|
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
|
|
||||||
@@ -116,6 +115,8 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
|
|
||||||
@Transient const val SPRITE_ROW_IDLE = 0
|
@Transient const val SPRITE_ROW_IDLE = 0
|
||||||
@Transient const val SPRITE_ROW_WALK = 1
|
@Transient const val SPRITE_ROW_WALK = 1
|
||||||
|
|
||||||
|
@Transient const val downDownMinLengthBase = 12
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@@ -173,7 +174,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
|
|
||||||
var isUpDown = false; protected set
|
var isUpDown = false; protected set
|
||||||
var isDownDown = false; protected set
|
var isDownDown = false; protected set
|
||||||
var downDownVirtually = false; internal set
|
var downButtonHeld = 0; internal set
|
||||||
var isLeftDown = false; protected set
|
var isLeftDown = false; protected set
|
||||||
var isRightDown = false; protected set
|
var isRightDown = false; protected set
|
||||||
var isJumpDown = false; protected set
|
var isJumpDown = false; protected set
|
||||||
@@ -221,7 +222,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
if (isNoClip) {
|
if (isNoClip) {
|
||||||
//grounded = true
|
//grounded = true
|
||||||
// platformToIgnore = null
|
// platformToIgnore = null
|
||||||
downDownVirtually = false
|
downButtonHeld = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset control box of AI
|
// reset control box of AI
|
||||||
@@ -248,13 +249,16 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val downDownMinLength: Int
|
||||||
|
get() = (downDownMinLengthBase * (gravitation.y.abs() / 9.8).sqrt()).ceilToInt()
|
||||||
|
|
||||||
private fun updateGamerControlBox() {
|
private fun updateGamerControlBox() {
|
||||||
if (isGamer) {
|
if (isGamer) {
|
||||||
isUpDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_up"))
|
isUpDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_up"))
|
||||||
isLeftDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_left"))
|
isLeftDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_left"))
|
||||||
isDownDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_down"))
|
isDownDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_down"))
|
||||||
isRightDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_right"))
|
isRightDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_right"))
|
||||||
isJumpDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_jump"))
|
isJumpDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_jump"))
|
||||||
|
|
||||||
val gamepad = App.gamepad
|
val gamepad = App.gamepad
|
||||||
|
|
||||||
@@ -264,7 +268,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
axisRX = gamepad.getAxis(App.getConfigInt("control_gamepad_axisrx"))
|
axisRX = gamepad.getAxis(App.getConfigInt("control_gamepad_axisrx"))
|
||||||
axisRY = gamepad.getAxis(App.getConfigInt("control_gamepad_axisry"))
|
axisRY = gamepad.getAxis(App.getConfigInt("control_gamepad_axisry"))
|
||||||
|
|
||||||
isJumpDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_jump")) ||
|
isJumpDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_jump")) ||
|
||||||
gamepad.getButton(App.getConfigInt("control_gamepad_ltrigger"))
|
gamepad.getButton(App.getConfigInt("control_gamepad_ltrigger"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,17 +292,14 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
}
|
}
|
||||||
|
|
||||||
// platform-related hacks
|
// platform-related hacks
|
||||||
// allow latching down downDownVirtually only when standing on a platform AND not jumping upwards
|
if (isDownDown || downButtonHeld in 1 until downDownMinLength) {
|
||||||
val occupyingTileHasPlatform = bodyTiles.filterNotNull().any { it.isPlatform }
|
downButtonHeld += 1
|
||||||
val feetTileHasPlatform = feetTiles.filterNotNull().any { it.isPlatform }
|
|
||||||
val feetTileIsAllPlatform = feetTiles.filterNotNull().all { it.isPlatform }
|
|
||||||
if (isDownDown && feetTileIsAllPlatform && (controllerV?.y ?: 0.0) >= 0.0) {// ||
|
|
||||||
// occupyingTileHasPlatform && !feetTileHasPlatform) { // FIXME commenting this out enables platform-ladder but falldown gets slowed down if the body passes thru the platform but I think this behav might be beneficial for player?
|
|
||||||
downDownVirtually = true
|
|
||||||
}
|
}
|
||||||
if (downDownVirtually && !occupyingTileHasPlatform && !feetTileIsAllPlatform) {
|
else {
|
||||||
downDownVirtually = false
|
downButtonHeld = 0
|
||||||
}
|
}
|
||||||
|
// TODO just disable "snap to ground" on collision solver if {player's body overlaps with the platform/downDownVirtually}?
|
||||||
|
// the point is: disable snap (or don't consider offending tiles as solid) for certain Y-pos only, tiles on Y+1 are still solid
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline val hasController: Boolean
|
private inline val hasController: Boolean
|
||||||
@@ -347,11 +348,11 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
// ↑F, ↓S
|
// ↑F, ↓S
|
||||||
if (isRightDown && !isLeftDown) {
|
if (isRightDown && !isLeftDown) {
|
||||||
walkHorizontal(false, AXIS_KEYBOARD)
|
walkHorizontal(false, AXIS_KEYBOARD)
|
||||||
prevHMoveKey = App.getConfigInt("control_key_right")
|
prevHMoveKey = ControlPresets.getKey("control_key_right")
|
||||||
} // ↓F, ↑S
|
} // ↓F, ↑S
|
||||||
else if (isLeftDown && !isRightDown) {
|
else if (isLeftDown && !isRightDown) {
|
||||||
walkHorizontal(true, AXIS_KEYBOARD)
|
walkHorizontal(true, AXIS_KEYBOARD)
|
||||||
prevHMoveKey = App.getConfigInt("control_key_left")
|
prevHMoveKey = ControlPresets.getKey("control_key_left")
|
||||||
} // ↓F, ↓S
|
} // ↓F, ↓S
|
||||||
/*else if (isLeftDown && isRightDown) {
|
/*else if (isLeftDown && isRightDown) {
|
||||||
if (prevHMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_LEFT)) {
|
if (prevHMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_LEFT)) {
|
||||||
@@ -375,11 +376,11 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
// ↑E, ↓D
|
// ↑E, ↓D
|
||||||
if (isDownDown && !isUpDown) {
|
if (isDownDown && !isUpDown) {
|
||||||
walkVertical(false, AXIS_KEYBOARD)
|
walkVertical(false, AXIS_KEYBOARD)
|
||||||
prevVMoveKey = App.getConfigInt("control_key_down")
|
prevVMoveKey = ControlPresets.getKey("control_key_down")
|
||||||
} // ↓E, ↑D
|
} // ↓E, ↑D
|
||||||
else if (isUpDown && !isDownDown) {
|
else if (isUpDown && !isDownDown) {
|
||||||
walkVertical(true, AXIS_KEYBOARD)
|
walkVertical(true, AXIS_KEYBOARD)
|
||||||
prevVMoveKey = App.getConfigInt("control_key_up")
|
prevVMoveKey = ControlPresets.getKey("control_key_up")
|
||||||
} // ↓E, ↓D
|
} // ↓E, ↓D
|
||||||
/*else if (isUpDown && isDownDown) {
|
/*else if (isUpDown && isDownDown) {
|
||||||
if (prevVMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_UP)) {
|
if (prevVMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_UP)) {
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
|||||||
forEachBlockbox { x, y, _, _ ->
|
forEachBlockbox { x, y, _, _ ->
|
||||||
if (!hasCollision) {
|
if (!hasCollision) {
|
||||||
val tile = world!!.getTileFromTerrain(x, y)
|
val tile = world!!.getTileFromTerrain(x, y)
|
||||||
if (BlockCodex[tile].isSolid || BlockCodex[tile].isActorBlock) {
|
if (!BlockCodex[tile].hasTag("INCONSEQUENTIAL")) {
|
||||||
hasCollision = true
|
hasCollision = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,7 +311,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
|||||||
forEachBlockbox { x, y, _, _ ->
|
forEachBlockbox { x, y, _, _ ->
|
||||||
if (!hasCollision) {
|
if (!hasCollision) {
|
||||||
val tile = world!!.getTileFromTerrain(x, y)
|
val tile = world!!.getTileFromTerrain(x, y)
|
||||||
if (BlockCodex[tile].isSolid || BlockCodex[tile].isActorBlock) {
|
if (!BlockCodex[tile].hasTag("INCONSEQUENTIAL")) {
|
||||||
hasCollision = true
|
hasCollision = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.gameactors
|
||||||
|
|
||||||
|
import net.torvald.terrarum.INGAME
|
||||||
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
|
import net.torvald.terrarum.langpack.Lang
|
||||||
|
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
|
||||||
|
import net.torvald.terrarum.modulebasegame.ui.UIWallCalendar
|
||||||
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-08.
|
||||||
|
*/
|
||||||
|
class FixtureWallCalendar : FixtureBase {
|
||||||
|
|
||||||
|
constructor() : super(
|
||||||
|
BlockBox(BlockBox.NO_COLLISION, 1, 1),
|
||||||
|
nameFun = { Lang["ITEM_CALENDAR"] },
|
||||||
|
mainUI = UIWallCalendar()
|
||||||
|
) {
|
||||||
|
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/calendar.tga")
|
||||||
|
|
||||||
|
density = 600.0
|
||||||
|
setHitboxDimension(TILE_SIZE, TILE_SIZE, 0, 1)
|
||||||
|
|
||||||
|
makeNewSprite(TextureRegionPack(itemImage.texture, TILE_SIZE, TILE_SIZE)).let {
|
||||||
|
it.setRowsAndFrames(1,1)
|
||||||
|
}
|
||||||
|
|
||||||
|
actorValue[AVKey.BASEMASS] = 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
override var tooltipText: String?
|
||||||
|
get() = Lang.getAndUseTemplate("CONTEXT_CALENDAR_DATE_FORMAT_YMD_DDD", false,
|
||||||
|
world!!.worldTime.years,
|
||||||
|
world!!.worldTime.getMonthNameFull(),
|
||||||
|
world!!.worldTime.calendarDay,
|
||||||
|
world!!.worldTime.getDayNameFull()
|
||||||
|
)//INGAME.world.worldTime.getFormattedCalendarDay()
|
||||||
|
set(value) {}
|
||||||
|
}
|
||||||
@@ -51,7 +51,7 @@ object BlockBase {
|
|||||||
|
|
||||||
// return false if there is a "solid" tile already
|
// return false if there is a "solid" tile already
|
||||||
if (isWall && BlockCodex[wallUnderCursor].isSolid ||
|
if (isWall && BlockCodex[wallUnderCursor].isSolid ||
|
||||||
!isWall && (BlockCodex[terrainUnderCursor].isSolid || BlockCodex[terrainUnderCursor].isActorBlock))
|
!isWall && !BlockCodex[terrainUnderCursor].hasTag("INCONSEQUENTIAL"))
|
||||||
return@mouseInInteractableRange -1L
|
return@mouseInInteractableRange -1L
|
||||||
|
|
||||||
// filter passed, do the job
|
// filter passed, do the job
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.gameitems
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-08.
|
||||||
|
*/
|
||||||
|
class ItemWallCalendar(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureWallCalendar") {
|
||||||
|
|
||||||
|
override var dynamicID: ItemID = originalID
|
||||||
|
override val originalName = "ITEM_CALENDAR"
|
||||||
|
override var baseMass = 1.0
|
||||||
|
override var stackable = true
|
||||||
|
override var inventoryCategory = Category.MISC
|
||||||
|
override val isUnique = false
|
||||||
|
override val isDynamic = false
|
||||||
|
override val materialId = ""
|
||||||
|
override val itemImage: TextureRegion
|
||||||
|
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/calendar.tga")
|
||||||
|
|
||||||
|
override var baseToolSize: Double? = baseMass
|
||||||
|
|
||||||
|
init {
|
||||||
|
equipPosition = EquipPosition.HAND_GRIP
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -133,7 +133,7 @@ class QuickSingleplayerWorldSavingThread(
|
|||||||
|
|
||||||
// Write Actors //
|
// Write Actors //
|
||||||
actorsList.forEachIndexed { count, it ->
|
actorsList.forEachIndexed { count, it ->
|
||||||
printdbg(this, "Writing actors... ${count+1}/${actorsList.size}")
|
printdbg(this, "Writing actors... ${count+1}/${actorsList.size} (${it.javaClass.canonicalName})")
|
||||||
|
|
||||||
val actorContent = EntryFile(WriteActor.encodeToByteArray64(it))
|
val actorContent = EntryFile(WriteActor.encodeToByteArray64(it))
|
||||||
val actor = DiskEntry(it.referenceID.toLong(), ROOT, creation_t, time_t, actorContent)
|
val actor = DiskEntry(it.referenceID.toLong(), ROOT, creation_t, time_t, actorContent)
|
||||||
|
|||||||
@@ -56,10 +56,10 @@ object ControlPanelCommon {
|
|||||||
|
|
||||||
val initialSel = optionsList.indexOf(App.getConfigString(optionName))
|
val initialSel = optionsList.indexOf(App.getConfigString(optionName))
|
||||||
|
|
||||||
println("labelFuns = ${labelFuns.map { it.invoke() }}")
|
// println("labelFuns = ${labelFuns.map { it.invoke() }}")
|
||||||
println("optionsList = $optionsList")
|
// println("optionsList = $optionsList")
|
||||||
println("optionName = $optionName; value = ${App.getConfigString(optionName)}")
|
// println("optionName = $optionName; value = ${App.getConfigString(optionName)}")
|
||||||
println("initialSel = $initialSel")
|
// println("initialSel = $initialSel")
|
||||||
|
|
||||||
if (initialSel < 0) throw IllegalArgumentException("config value '${App.getConfigString(optionName)}' for option '$optionName' is not found on the options list")
|
if (initialSel < 0) throw IllegalArgumentException("config value '${App.getConfigString(optionName)}' for option '$optionName' is not found on the options list")
|
||||||
|
|
||||||
@@ -69,6 +69,19 @@ object ControlPanelCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (args.startsWith("spinnersel,")) {
|
||||||
|
val labelFuns = arg.subList(1, arg.size).map { { it } }
|
||||||
|
val optionsList = arg.subList(1, arg.size).map { it.toInt() }
|
||||||
|
|
||||||
|
val initialSel = optionsList.indexOf(App.getConfigInt(optionName))
|
||||||
|
if (initialSel < 0) throw IllegalArgumentException("config value '${App.getConfigInt(optionName)}' for option '$optionName' is not found on the options list")
|
||||||
|
|
||||||
|
UIItemTextSelector(parent, x, y, labelFuns, initialSel, CONFIG_SPINNER_WIDTH, clickToShowPalette = false, useSpinnerButtons = true) to { it: UIItem, optionStr: String ->
|
||||||
|
(it as UIItemTextSelector).selectionChangeListener = {
|
||||||
|
App.setConfig(optionStr, optionsList[it])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (args.startsWith("spinner,")) {
|
else if (args.startsWith("spinner,")) {
|
||||||
UIItemSpinner(parent, x, y, App.getConfigInt(optionName), arg[1].toInt(), arg[2].toInt(), arg[3].toInt(), CONFIG_SPINNER_WIDTH, numberToTextFunction = { "${it.toLong()}" }) to { it: UIItem, optionStr: String ->
|
UIItemSpinner(parent, x, y, App.getConfigInt(optionName), arg[1].toInt(), arg[2].toInt(), arg[3].toInt(), CONFIG_SPINNER_WIDTH, numberToTextFunction = { "${it.toLong()}" }) to { it: UIItem, optionStr: String ->
|
||||||
(it as UIItemSpinner).selectionChangeListener = {
|
(it as UIItemSpinner).selectionChangeListener = {
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
|||||||
*/
|
*/
|
||||||
class UIBasicInfo() : UICanvas() {
|
class UIBasicInfo() : UICanvas() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
handler.allowESCtoClose = false
|
||||||
|
}
|
||||||
|
|
||||||
val player: ActorHumanoid?
|
val player: ActorHumanoid?
|
||||||
get() = Terrarum.ingame?.actorNowPlaying
|
get() = Terrarum.ingame?.actorNowPlaying
|
||||||
|
|
||||||
@@ -42,7 +46,7 @@ class UIBasicInfo() : UICanvas() {
|
|||||||
ELuptimer += delta
|
ELuptimer += delta
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouseUp || Gdx.input.isKeyPressed(App.getConfigInt("control_key_interact"))) {
|
if (mouseUp || Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_interact"))) {
|
||||||
ELuptimer = 0f
|
ELuptimer = 0f
|
||||||
ELon = true
|
ELon = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ import net.torvald.terrarum.ui.UICanvas
|
|||||||
*/
|
*/
|
||||||
class UICheatDetected : UICanvas() {
|
class UICheatDetected : UICanvas() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
handler.allowESCtoClose = false
|
||||||
|
}
|
||||||
|
|
||||||
override var width: Int
|
override var width: Int
|
||||||
get() = App.scr.width
|
get() = App.scr.width
|
||||||
set(value) { throw UnsupportedOperationException() }
|
set(value) { throw UnsupportedOperationException() }
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
else
|
else
|
||||||
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}\u3000 " +
|
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}\u3000 " +
|
||||||
"$gamepadLabelLEFTRIGHT ${Lang["GAME_OBJECTIVE_MULTIPLIER"]}\u3000 " +
|
"$gamepadLabelLEFTRIGHT ${Lang["GAME_OBJECTIVE_MULTIPLIER"]}\u3000 " +
|
||||||
@@ -125,7 +125,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
|
|||||||
// If the player has the required item, use it; otherwise, will take an item from the ItemCodex
|
// If the player has the required item, use it; otherwise, will take an item from the ItemCodex
|
||||||
player.itemList.filter { (itm, qty) ->
|
player.itemList.filter { (itm, qty) ->
|
||||||
ItemCodex[itm]?.tags?.contains(ingredient.key) == true && qty >= ingredient.qty
|
ItemCodex[itm]?.tags?.contains(ingredient.key) == true && qty >= ingredient.qty
|
||||||
}.maxByOrNull { it.qty }?.itm ?: ((ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.tags.contains(ingredient.key)) it.key else null }) ?: throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed"))
|
}.maxByOrNull { it.qty }?.itm ?: ((ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.hasTag(ingredient.key)) it.key else null }) ?: throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed"))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ingredient.key
|
ingredient.key
|
||||||
@@ -234,7 +234,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
|
|||||||
// don't rely on highlightedness of the button to determine the item on the button is the selected
|
// don't rely on highlightedness of the button to determine the item on the button is the selected
|
||||||
// ingredient (because I don't fully trust my code lol)
|
// ingredient (because I don't fully trust my code lol)
|
||||||
val targetItemToAlter = recipe.ingredients.filter { // altering recipe doesn't make sense if player selected a recipe that requires no tag-ingredients
|
val targetItemToAlter = recipe.ingredients.filter { // altering recipe doesn't make sense if player selected a recipe that requires no tag-ingredients
|
||||||
(it.keyMode == CraftingCodex.CraftingItemKeyMode.TAG && gameItem.tags.contains(it.key))
|
(it.keyMode == CraftingCodex.CraftingItemKeyMode.TAG && gameItem.hasTag(it.key))
|
||||||
}.let {
|
}.let {
|
||||||
if (it.size > 1)
|
if (it.size > 1)
|
||||||
println("[UICrafting] Your recipe seems to have two similar ingredients defined\n" +
|
println("[UICrafting] Your recipe seems to have two similar ingredients defined\n" +
|
||||||
@@ -245,7 +245,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
|
|||||||
|
|
||||||
targetItemToAlter?.let {
|
targetItemToAlter?.let {
|
||||||
val oldItem = _getItemListIngredients().getInventory().itemList.first { itemPair ->
|
val oldItem = _getItemListIngredients().getInventory().itemList.first { itemPair ->
|
||||||
(it.keyMode == CraftingCodex.CraftingItemKeyMode.TAG && ItemCodex[itemPair.itm]!!.tags.contains(it.key))
|
(it.keyMode == CraftingCodex.CraftingItemKeyMode.TAG && ItemCodex[itemPair.itm]!!.hasTag(it.key))
|
||||||
}
|
}
|
||||||
changeIngredient(oldItem, itemID)
|
changeIngredient(oldItem, itemID)
|
||||||
refreshCraftButtonStatus()
|
refreshCraftButtonStatus()
|
||||||
@@ -279,7 +279,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
|
|||||||
// If the player has the required item, use it; otherwise, will take an item from the ItemCodex
|
// If the player has the required item, use it; otherwise, will take an item from the ItemCodex
|
||||||
val selectedItem = playerInventory.itemList.filter { (itm, qty) ->
|
val selectedItem = playerInventory.itemList.filter { (itm, qty) ->
|
||||||
ItemCodex[itm]?.tags?.contains(ingredient.key) == true && qty >= ingredient.qty
|
ItemCodex[itm]?.tags?.contains(ingredient.key) == true && qty >= ingredient.qty
|
||||||
}.maxByOrNull { it.qty }?.itm ?: ((ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.tags.contains(ingredient.key)) it.key else null }) ?: throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed"))
|
}.maxByOrNull { it.qty }?.itm ?: ((ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.hasTag(ingredient.key)) it.key else null }) ?: throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed"))
|
||||||
|
|
||||||
// printdbg(this, "Adding ingredients by tag ${selectedItem} (${ingredient.qty})")
|
// printdbg(this, "Adding ingredients by tag ${selectedItem} (${ingredient.qty})")
|
||||||
selectedItem
|
selectedItem
|
||||||
|
|||||||
@@ -24,18 +24,18 @@ class UIGraphicsControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
init {
|
init {
|
||||||
ControlPanelCommon.register(this, width, "basegame.graphicscontrolpanel", arrayOf(
|
ControlPanelCommon.register(this, width, "basegame.graphicscontrolpanel", arrayOf(
|
||||||
arrayOf("", { Lang["CREDITS_VFX"] }, "h1"),
|
arrayOf("", { Lang["CREDITS_VFX"] }, "h1"),
|
||||||
arrayOf("fx_dither", { Lang["MENU_OPTIONS_DITHER"] }, "toggle"),
|
arrayOf("fx_dither", { Lang["MENU_OPTIONS_DITHER"] }, "toggle"),
|
||||||
arrayOf("fx_backgroundblur", { Lang["MENU_OPTIONS_BLUR"] }, "toggle"),
|
arrayOf("fx_backgroundblur", { Lang["MENU_OPTIONS_BLUR"] }, "toggle"),
|
||||||
arrayOf("maxparticles", { Lang["MENU_OPTIONS_PARTICLES"] }, "spinner,256,1024,256"),
|
arrayOf("maxparticles", { Lang["MENU_OPTIONS_PARTICLES"] }, "spinner,256,1024,256"),
|
||||||
arrayOf("", { Lang["MENU_OPTIONS_DISPLAY"] }, "h1"),
|
arrayOf("", { Lang["MENU_OPTIONS_DISPLAY"] }, "h1"),
|
||||||
arrayOf("screenwidth,screenheight", { Lang["MENU_OPTIONS_RESOLUTION"] }, "typeinres"),
|
arrayOf("screenwidth,screenheight", { Lang["MENU_OPTIONS_RESOLUTION"] }, "typeinres"),
|
||||||
arrayOf("screenmagnifying", { Lang["GAME_ACTION_ZOOM"] }, "spinnerd,1.0,2.0,0.05"),
|
arrayOf("screenmagnifying", { Lang["GAME_ACTION_ZOOM"] }, "spinnerd,1.0,2.0,0.05"),
|
||||||
arrayOf("screenmagnifyingfilter", { Lang["MENU_OPTIONS_FILTERING_MODE"] }, "textsel,none=MENU_OPTIONS_NONE,bilinear=MENU_OPTIONS_FILTERING_BILINEAR,hq2x=MENU_OPTIONS_FILTERING_HQ2X_DNT"),
|
arrayOf("screenmagnifyingfilter", { Lang["MENU_OPTIONS_FILTERING_MODE"] }, "textsel,none=MENU_OPTIONS_NONE,bilinear=MENU_OPTIONS_FILTERING_BILINEAR,hq2x=MENU_OPTIONS_FILTERING_HQ2X_DNT"),
|
||||||
arrayOf("displayfps", { Lang["MENU_LABEL_FRAMESPERSEC"] }, "spinner,0,300,2"),
|
arrayOf("displayfps", { Lang["MENU_LABEL_FRAMESPERSEC"] }, "spinner,0,300,2"),
|
||||||
arrayOf("usevsync", { Lang["MENU_OPTIONS_VSYNC"] }, "toggle"),
|
arrayOf("usevsync", { Lang["MENU_OPTIONS_VSYNC"] }, "toggle"),
|
||||||
arrayOf("", { "(${Lang["MENU_LABEL_RESTART_REQUIRED"]})" }, "p"),
|
arrayOf("", { "(${Lang["MENU_LABEL_RESTART_REQUIRED"]})" }, "p"),
|
||||||
arrayOf("", { Lang["MENU_LABEL_STREAMING"] }, "h1"),
|
arrayOf("", { Lang["MENU_LABEL_STREAMING"] }, "h1"),
|
||||||
arrayOf("fx_streamerslayout", { Lang["MENU_OPTIONS_STREAMERS_LAYOUT"] }, "toggle"),
|
arrayOf("fx_streamerslayout", { Lang["MENU_OPTIONS_STREAMERS_LAYOUT"] }, "toggle"),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|||||||
import net.torvald.unicode.EMDASH
|
import net.torvald.unicode.EMDASH
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.CommonResourcePool
|
import net.torvald.terrarum.CommonResourcePool
|
||||||
|
import net.torvald.terrarum.ControlPresets
|
||||||
import net.torvald.terrarum.gamecontroller.*
|
import net.torvald.terrarum.gamecontroller.*
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.linearSearch
|
import net.torvald.terrarum.linearSearch
|
||||||
@@ -318,7 +319,7 @@ private class UIItemInputKeycap(
|
|||||||
else if (parent.shiftin && keysymsLow[1]?.isNotEmpty() == true) keysymsLow[1]
|
else if (parent.shiftin && keysymsLow[1]?.isNotEmpty() == true) keysymsLow[1]
|
||||||
else keysymsLow[0]) ?: ""
|
else keysymsLow[0]) ?: ""
|
||||||
|
|
||||||
val keysym0: Array<String?> = if (KeyToggler.isOn(App.getConfigInt("control_key_toggleime"))) {
|
val keysym0: Array<String?> = if (KeyToggler.isOn(ControlPresets.getKey("control_key_toggleime"))) {
|
||||||
if (parent.highlayer == null) arrayOf(keysymLow,keysymLow,keysymLow,keysymLow)
|
if (parent.highlayer == null) arrayOf(keysymLow,keysymLow,keysymLow,keysymLow)
|
||||||
else {
|
else {
|
||||||
val keysyms = parent.highlayer!!.config.symbols
|
val keysyms = parent.highlayer!!.config.symbols
|
||||||
|
|||||||
161
src/net/torvald/terrarum/modulebasegame/ui/UIImportAvatar.kt
Normal file
161
src/net/torvald/terrarum/modulebasegame/ui/UIImportAvatar.kt
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.ui
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.Input
|
||||||
|
import com.badlogic.gdx.graphics.Camera
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.Second
|
||||||
|
import net.torvald.terrarum.ceilToInt
|
||||||
|
import net.torvald.terrarum.gamecontroller.*
|
||||||
|
import net.torvald.terrarum.langpack.Lang
|
||||||
|
import net.torvald.terrarum.serialise.Ascii85Codec
|
||||||
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
import net.torvald.terrarum.ui.UIItem
|
||||||
|
import net.torvald.terrarum.ui.UIItemTextButton
|
||||||
|
import net.torvald.terrarum.utils.Clipboard
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-24.
|
||||||
|
*/
|
||||||
|
class UIImportAvatar(val remoCon: UIRemoCon) : Advanceable() {
|
||||||
|
|
||||||
|
override var width = 480 // SAVE_CELL_WIDTH
|
||||||
|
override var height = 480
|
||||||
|
override var openCloseTime: Second = OPENCLOSE_GENERIC
|
||||||
|
|
||||||
|
private val drawX = (Toolkit.drawWidth - width) / 2
|
||||||
|
private val drawY = (App.scr.height - height) / 2
|
||||||
|
private val cols = 80
|
||||||
|
private val rows = 30
|
||||||
|
private val goButtonWidth = 180
|
||||||
|
|
||||||
|
|
||||||
|
private val codeBox = UIItemCodeBox(this, (Toolkit.drawWidth - App.fontSmallNumbers.W * cols) / 2, drawY, cols, rows)
|
||||||
|
|
||||||
|
private val clearButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_IO_CLEAR"] }, drawX + (width/2 - goButtonWidth) / 2, drawY + height - 24 - 34, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
private val pasteButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_LABEL_PASTE"] }, drawX + width/2 + (width/2 - goButtonWidth) / 2, drawY + height - 24 - 34, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
|
||||||
|
|
||||||
|
private val backButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_LABEL_BACK"] }, drawX + (width/2 - goButtonWidth) / 2, drawY + height - 24, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
private val goButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_IO_IMPORT"] }, drawX + width/2 + (width/2 - goButtonWidth) / 2, drawY + height - 24, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addUIitem(codeBox)
|
||||||
|
addUIitem(clearButton)
|
||||||
|
addUIitem(pasteButton)
|
||||||
|
addUIitem(backButton)
|
||||||
|
addUIitem(goButton)
|
||||||
|
|
||||||
|
clearButton.clickOnceListener = { _,_ ->
|
||||||
|
codeBox.clearTextBuffer()
|
||||||
|
}
|
||||||
|
pasteButton.clickOnceListener = { _,_ ->
|
||||||
|
codeBox.pasteFromClipboard()
|
||||||
|
}
|
||||||
|
backButton.clickOnceListener = { _,_ ->
|
||||||
|
remoCon.openUI(UILoadSavegame(remoCon))
|
||||||
|
}
|
||||||
|
goButton.clickOnceListener = { _,_ ->
|
||||||
|
doImport()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun updateUI(delta: Float) {
|
||||||
|
uiItems.forEach { it.update(delta) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||||
|
uiItems.forEach { it.render(batch, camera) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun advanceMode(button: UIItem) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doImport() {
|
||||||
|
val rawStr = codeBox.textBuffer.toString()
|
||||||
|
// sanity check
|
||||||
|
|
||||||
|
|
||||||
|
val ascii85codec = Ascii85Codec((33..117).map { it.toChar() }.joinToString(""))
|
||||||
|
val ascii85str = rawStr.substring(2 until rawStr.length - 2).replace("z", "!!!!!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UIItemCodeBox(parent: UIImportAvatar, initialX: Int, initialY: Int, val cols: Int = 80, val rows: Int = 24) : UIItem(parent, initialX, initialY) {
|
||||||
|
|
||||||
|
override val width = App.fontSmallNumbers.W * cols
|
||||||
|
override val height = App.fontSmallNumbers.H * rows
|
||||||
|
override fun dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private var highlightCol: Color = Toolkit.Theme.COL_INACTIVE
|
||||||
|
|
||||||
|
var selected = false
|
||||||
|
|
||||||
|
private var textCursorPosition = 0
|
||||||
|
internal var textBuffer = StringBuilder()
|
||||||
|
|
||||||
|
fun pasteFromClipboard() {
|
||||||
|
textBuffer.clear()
|
||||||
|
Clipboard.fetch().forEach {
|
||||||
|
if (it.code in 33..122) textBuffer.append(it)
|
||||||
|
}
|
||||||
|
textCursorPosition += textBuffer.length
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(delta: Float) {
|
||||||
|
super.update(delta)
|
||||||
|
// if (!selected && mousePushed)
|
||||||
|
// selected = true
|
||||||
|
// else if (selected && mouseDown && !mouseUp)
|
||||||
|
// selected = false
|
||||||
|
|
||||||
|
if (textBuffer.isEmpty() && (Gdx.input.isKeyJustPressed(Input.Keys.V) && (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) || Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT)))) {
|
||||||
|
pasteFromClipboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(batch: SpriteBatch, camera: Camera) {
|
||||||
|
// draw box backgrounds
|
||||||
|
batch.color = UIInventoryFull.CELL_COL
|
||||||
|
Toolkit.fillArea(batch, posX, posY, width, height)
|
||||||
|
|
||||||
|
// draw borders
|
||||||
|
batch.color = if (selected) Toolkit.Theme.COL_SELECTED else if (mouseUp) Toolkit.Theme.COL_MOUSE_UP else Toolkit.Theme.COL_INACTIVE
|
||||||
|
Toolkit.drawBoxBorder(batch, posX - 1, posY - 1, width + 2, height + 2)
|
||||||
|
|
||||||
|
// draw texts
|
||||||
|
if (textBuffer.isEmpty()) {
|
||||||
|
batch.color = Toolkit.Theme.COL_INACTIVE
|
||||||
|
App.fontGame.draw(batch, Lang["CONTEXT_IMPORT_AVATAR_INSTRUCTION_1"], posX + 5, posY)
|
||||||
|
App.fontGame.draw(batch, Lang["CONTEXT_IMPORT_AVATAR_INSTRUCTION_2"], posX + 5f, posY + App.fontGame.lineHeight)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
val scroll = ((textBuffer.length.toDouble() / cols).ceilToInt() - rows).coerceAtLeast(0)
|
||||||
|
for (i in scroll * cols until textBuffer.length) {
|
||||||
|
val c = textBuffer[i]
|
||||||
|
val x = ((i - scroll * cols) % cols) * App.fontSmallNumbers.W.toFloat()
|
||||||
|
val y = ((i - scroll * cols) / cols) * App.fontSmallNumbers.H.toFloat()
|
||||||
|
|
||||||
|
App.fontSmallNumbers.draw(batch, "$c", posX + x, posY + y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearTextBuffer() {
|
||||||
|
textBuffer.clear()
|
||||||
|
textCursorPosition = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package net.torvald.terrarum.modulebasegame.ui
|
|||||||
import com.badlogic.gdx.graphics.Camera
|
import com.badlogic.gdx.graphics.Camera
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.App.*
|
import net.torvald.terrarum.App.*
|
||||||
@@ -19,7 +18,7 @@ import net.torvald.unicode.*
|
|||||||
* Created by minjaesong on 2017-10-21.
|
* Created by minjaesong on 2017-10-21.
|
||||||
*/
|
*/
|
||||||
class UIInventoryFull(
|
class UIInventoryFull(
|
||||||
toggleKeyLiteral: Int? = App.getConfigInt("control_key_inventory"), toggleButtonLiteral: Int? = App.getConfigInt("control_gamepad_start"),
|
toggleKeyLiteral: String? = "control_key_inventory", toggleButtonLiteral: String? = "control_gamepad_start",
|
||||||
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
||||||
customPositioning: Boolean = false, // mainly used by vital meter
|
customPositioning: Boolean = false, // mainly used by vital meter
|
||||||
doNotWarnConstant: Boolean = false
|
doNotWarnConstant: Boolean = false
|
||||||
@@ -157,16 +156,15 @@ class UIInventoryFull(
|
|||||||
//val INVENTORY_CELLS_OFFSET_Y: Int = 107 + (AppLoader.terrarumAppConfig.screenH - internalHeight) / 2
|
//val INVENTORY_CELLS_OFFSET_Y: Int = 107 + (AppLoader.terrarumAppConfig.screenH - internalHeight) / 2
|
||||||
|
|
||||||
init {
|
init {
|
||||||
handler.allowESCtoClose = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val SP = "\u3000 "
|
private val SP = "\u3000 "
|
||||||
val listControlHelp: String
|
val listControlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||||
"$KEYCAP_LEFT_MOUSE ${Lang["GAME_INVENTORY_USE"]}$SP" +
|
"$KEYCAP_LEFT_MOUSE ${Lang["GAME_INVENTORY_USE"]}$SP" +
|
||||||
"$KEYCAP_1$ENDASH\u2009$KEYCAP_0 ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
|
"$KEYCAP_1$ENDASH\u2009$KEYCAP_0 ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_discard"))} ${Lang["GAME_INVENTORY_DROP"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_discard"))} ${Lang["GAME_INVENTORY_DROP"]}"
|
||||||
else
|
else
|
||||||
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||||
"$gamepadLabelLT ${Lang["CONTEXT_ITEM_MAP"]}$SP" +
|
"$gamepadLabelLT ${Lang["CONTEXT_ITEM_MAP"]}$SP" +
|
||||||
@@ -176,7 +174,7 @@ class UIInventoryFull(
|
|||||||
"$gamepadLabelEast ${Lang["GAME_INVENTORY_DROP"]}"
|
"$gamepadLabelEast ${Lang["GAME_INVENTORY_DROP"]}"
|
||||||
val minimapControlHelp: String
|
val minimapControlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||||
"$KEYCAP_LEFT_MOUSE$KEYCAP_MOVE ${Lang["GAME_ACTION_MOVE_VERB"]}"
|
"$KEYCAP_LEFT_MOUSE$KEYCAP_MOVE ${Lang["GAME_ACTION_MOVE_VERB"]}"
|
||||||
else
|
else
|
||||||
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||||
@@ -184,7 +182,7 @@ class UIInventoryFull(
|
|||||||
"$gamepadLabelRT ${Lang["GAME_INVENTORY"]}"
|
"$gamepadLabelRT ${Lang["GAME_INVENTORY"]}"
|
||||||
val gameMenuControlHelp: String
|
val gameMenuControlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
else
|
else
|
||||||
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||||
"$gamepadLabelLT ${Lang["GAME_INVENTORY"]}"
|
"$gamepadLabelLT ${Lang["GAME_INVENTORY"]}"
|
||||||
@@ -250,7 +248,7 @@ class UIInventoryFull(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allow "control_key_gamemenu" to open this UI and bring system menu immediately
|
// allow "control_key_gamemenu" to open this UI and bring system menu immediately
|
||||||
this.handler.toggleKeyExtra.add { App.getConfigInt("control_key_gamemenu") }
|
this.handler.toggleKeyExtra.add("control_key_gamemenu" )
|
||||||
this.handler.toggleKeyExtraAction.add {
|
this.handler.toggleKeyExtraAction.add {
|
||||||
if (it.isClosed) {
|
if (it.isClosed) {
|
||||||
INGAME.setTooltipMessage(null)
|
INGAME.setTooltipMessage(null)
|
||||||
@@ -264,7 +262,7 @@ class UIInventoryFull(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allow "control_key_crafting" to open this UI and bring system menu immediately
|
// allow "control_key_crafting" to open this UI and bring system menu immediately
|
||||||
this.handler.toggleKeyExtra.add { App.getConfigInt("control_key_crafting") }
|
this.handler.toggleKeyExtra.add("control_key_crafting")
|
||||||
this.handler.toggleKeyExtraAction.add {
|
this.handler.toggleKeyExtraAction.add {
|
||||||
if (it.isClosed) {
|
if (it.isClosed) {
|
||||||
INGAME.setTooltipMessage(null)
|
INGAME.setTooltipMessage(null)
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import com.badlogic.gdx.graphics.Camera
|
|||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
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.*
|
||||||
import net.torvald.terrarum.CommonResourcePool
|
|
||||||
import net.torvald.terrarum.DefaultConfig
|
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.ui.*
|
import net.torvald.terrarum.ui.*
|
||||||
|
|
||||||
@@ -37,16 +35,16 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
|
|
||||||
private val keycaps = hashMapOf(
|
private val keycaps = hashMapOf(
|
||||||
Input.Keys.GRAVE to UIItemKeycap(this, 1, 1, null, oneu, ""),
|
Input.Keys.GRAVE to UIItemKeycap(this, 1, 1, null, oneu, ""),
|
||||||
Input.Keys.NUM_1 to UIItemKeycap(this, 33,1, Input.Keys.NUM_1, oneu, "1,3"),
|
Input.Keys.NUM_1 to UIItemKeycap(this, 33,1, null, oneu, "1,3"),
|
||||||
Input.Keys.NUM_2 to UIItemKeycap(this, 65,1, Input.Keys.NUM_2, oneu, "2,3"),
|
Input.Keys.NUM_2 to UIItemKeycap(this, 65,1, null, oneu, "2,3"),
|
||||||
Input.Keys.NUM_3 to UIItemKeycap(this, 97,1, Input.Keys.NUM_3, oneu, "3,3"),
|
Input.Keys.NUM_3 to UIItemKeycap(this, 97,1, null, oneu, "3,3"),
|
||||||
Input.Keys.NUM_4 to UIItemKeycap(this, 129,1, Input.Keys.NUM_4, oneu, "4,3"),
|
Input.Keys.NUM_4 to UIItemKeycap(this, 129,1, null, oneu, "4,3"),
|
||||||
Input.Keys.NUM_5 to UIItemKeycap(this, 161,1, Input.Keys.NUM_5, oneu, "5,3"),
|
Input.Keys.NUM_5 to UIItemKeycap(this, 161,1, null, oneu, "5,3"),
|
||||||
Input.Keys.NUM_6 to UIItemKeycap(this, 193,1, Input.Keys.NUM_6, oneu, "6,3"),
|
Input.Keys.NUM_6 to UIItemKeycap(this, 193,1, null, oneu, "6,3"),
|
||||||
Input.Keys.NUM_7 to UIItemKeycap(this, 225,1, Input.Keys.NUM_7, oneu, "7,3"),
|
Input.Keys.NUM_7 to UIItemKeycap(this, 225,1, null, oneu, "7,3"),
|
||||||
Input.Keys.NUM_8 to UIItemKeycap(this, 257,1, Input.Keys.NUM_8, oneu, "8,3"),
|
Input.Keys.NUM_8 to UIItemKeycap(this, 257,1, null, oneu, "8,3"),
|
||||||
Input.Keys.NUM_9 to UIItemKeycap(this, 289,1, Input.Keys.NUM_9, oneu, "9,3"),
|
Input.Keys.NUM_9 to UIItemKeycap(this, 289,1, null, oneu, "9,3"),
|
||||||
Input.Keys.NUM_0 to UIItemKeycap(this, 321,1, Input.Keys.NUM_0, oneu, "0,3"),
|
Input.Keys.NUM_0 to UIItemKeycap(this, 321,1, null, oneu, "0,3"),
|
||||||
Input.Keys.MINUS to UIItemKeycap(this, 353,1, Input.Keys.MINUS, oneu, "10,3"),
|
Input.Keys.MINUS to UIItemKeycap(this, 353,1, Input.Keys.MINUS, oneu, "10,3"),
|
||||||
Input.Keys.EQUALS to UIItemKeycap(this, 385,1, Input.Keys.EQUALS, oneu, "11,3"),
|
Input.Keys.EQUALS to UIItemKeycap(this, 385,1, Input.Keys.EQUALS, oneu, "11,3"),
|
||||||
Input.Keys.BACKSPACE to UIItemKeycap(this, 417,1, Input.Keys.BACKSPACE, 60, "24,5"),
|
Input.Keys.BACKSPACE to UIItemKeycap(this, 417,1, Input.Keys.BACKSPACE, 60, "24,5"),
|
||||||
@@ -105,25 +103,39 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
) // end of keycaps
|
) // end of keycaps
|
||||||
|
|
||||||
private val resetButtonWidth = 140
|
private val resetButtonWidth = 140
|
||||||
private val buttonReset = UIItemTextButton(this,
|
private val presetButtonWidth = 200
|
||||||
|
/*private val buttonReset = UIItemTextButton(this,
|
||||||
{ Lang["MENU_LABEL_RESET"] },
|
{ Lang["MENU_LABEL_RESET"] },
|
||||||
kbx + (width - resetButtonWidth) / 2,
|
kbx + (width - resetButtonWidth) / 2,
|
||||||
kby + 162 + 12,
|
kby + 162 + 16,
|
||||||
resetButtonWidth,
|
resetButtonWidth,
|
||||||
hasBorder = true,
|
hasBorder = true,
|
||||||
alignment = UIItemTextButton.Companion.Alignment.CENTRE
|
alignment = UIItemTextButton.Companion.Alignment.CENTRE
|
||||||
|
)*/
|
||||||
|
private val presetSelector = UIItemTextSelector(this,
|
||||||
|
kbx + (width - presetButtonWidth) / 2,
|
||||||
|
kby + 162 + 16,
|
||||||
|
ControlPresets.presetLabels.map { { it } },
|
||||||
|
ControlPresets.presetLabels.indexOf(App.getConfigString("control_preset_keyboard")),
|
||||||
|
presetButtonWidth,
|
||||||
|
clickToShowPalette = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val controlPalette = UIItemControlPaletteBaloon(this, (Toolkit.drawWidth - 500) / 2, kby + 219)
|
private val controlPalette = UIItemControlPaletteBaloon(this, (Toolkit.drawWidth - 500) / 2, kby + 227)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
||||||
keycaps.values.forEach { addUIitem(it) }
|
keycaps.values.forEach { addUIitem(it) }
|
||||||
updateKeycaps()
|
updateKeycaps()
|
||||||
|
|
||||||
buttonReset.clickOnceListener = { x, y ->
|
/*buttonReset.clickOnceListener = { x, y ->
|
||||||
resetKeyConfig()
|
resetKeyConfig()
|
||||||
updateKeycaps()
|
updateKeycaps()
|
||||||
|
}*/
|
||||||
|
|
||||||
|
presetSelector.selectionChangeListener = { index ->
|
||||||
|
App.setConfig("control_preset_keyboard", ControlPresets.presetLabels[index])
|
||||||
|
updateKeycaps()
|
||||||
}
|
}
|
||||||
|
|
||||||
// addUIitem(keyboardLayoutSelection)
|
// addUIitem(keyboardLayoutSelection)
|
||||||
@@ -152,18 +164,18 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
private fun updateKeycaps() {
|
private fun updateKeycaps() {
|
||||||
keycaps.values.forEach { it.symbolControl = null }
|
keycaps.values.forEach { it.symbolControl = null }
|
||||||
// read config and put icons. Item order irrelevant
|
// read config and put icons. Item order irrelevant
|
||||||
keycaps[App.getConfigInt("control_key_up")]?.symbolControl = Keebsym.UP
|
keycaps[ControlPresets.getKey("control_key_up")]?.symbolControl = Keebsym.UP
|
||||||
keycaps[App.getConfigInt("control_key_left")]?.symbolControl = Keebsym.LEFT
|
keycaps[ControlPresets.getKey("control_key_left")]?.symbolControl = Keebsym.LEFT
|
||||||
keycaps[App.getConfigInt("control_key_down")]?.symbolControl = Keebsym.DOWN
|
keycaps[ControlPresets.getKey("control_key_down")]?.symbolControl = Keebsym.DOWN
|
||||||
keycaps[App.getConfigInt("control_key_right")]?.symbolControl = Keebsym.RIGHT
|
keycaps[ControlPresets.getKey("control_key_right")]?.symbolControl = Keebsym.RIGHT
|
||||||
keycaps[App.getConfigInt("control_key_jump")]?.symbolControl = Keebsym.JUMP
|
keycaps[ControlPresets.getKey("control_key_jump")]?.symbolControl = Keebsym.JUMP
|
||||||
keycaps[App.getConfigInt("control_key_zoom")]?.symbolControl = Keebsym.ZOOM
|
keycaps[ControlPresets.getKey("control_key_zoom")]?.symbolControl = Keebsym.ZOOM
|
||||||
keycaps[App.getConfigInt("control_key_inventory")]?.symbolControl = Keebsym.INVENTORY
|
keycaps[ControlPresets.getKey("control_key_inventory")]?.symbolControl = Keebsym.INVENTORY
|
||||||
keycaps[App.getConfigInt("control_key_movementaux")]?.symbolControl = Keebsym.HOOK
|
keycaps[ControlPresets.getKey("control_key_movementaux")]?.symbolControl = Keebsym.HOOK
|
||||||
keycaps[App.getConfigInt("control_key_quicksel")]?.symbolControl = Keebsym.PIE
|
keycaps[ControlPresets.getKey("control_key_quicksel")]?.symbolControl = Keebsym.PIE
|
||||||
keycaps[App.getConfigInt("control_key_gamemenu")]?.symbolControl = Keebsym.MENU
|
keycaps[ControlPresets.getKey("control_key_gamemenu")]?.symbolControl = Keebsym.MENU
|
||||||
keycaps[App.getConfigInt("control_key_toggleime")]?.symbolControl = Keebsym.IME()
|
keycaps[ControlPresets.getKey("control_key_toggleime")]?.symbolControl = Keebsym.IME()
|
||||||
keycaps[App.getConfigInt("control_key_crafting")]?.symbolControl = Keebsym.CRAFTING
|
keycaps[ControlPresets.getKey("control_key_crafting")]?.symbolControl = Keebsym.CRAFTING
|
||||||
}
|
}
|
||||||
|
|
||||||
internal var keycapClicked = -13372
|
internal var keycapClicked = -13372
|
||||||
@@ -176,14 +188,14 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
override fun updateUI(delta: Float) {
|
override fun updateUI(delta: Float) {
|
||||||
uiItems.forEach {
|
uiItems.forEach {
|
||||||
it.update(delta)
|
it.update(delta)
|
||||||
if (it is UIItemKeycap && it.mousePushed) {
|
if (it is UIItemKeycap && it.mousePushed && ControlPresets.presetLabels[presetSelector.selection] == "Custom") {
|
||||||
it.selected = true
|
it.selected = true
|
||||||
// println("key ${it.key}; selected = ${it.selected}")
|
// println("key ${it.key}; selected = ${it.selected}")
|
||||||
keycapClicked = it.key ?: -13372
|
keycapClicked = it.key ?: -13372
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonReset.update(delta)
|
presetSelector.update(delta)
|
||||||
|
|
||||||
controlPalette.update(delta)
|
controlPalette.update(delta)
|
||||||
}
|
}
|
||||||
@@ -194,7 +206,7 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
// batch.color = fillCol
|
// batch.color = fillCol
|
||||||
// Toolkit.fillArea(batch, drawX, drawY, width, height)
|
// Toolkit.fillArea(batch, drawX, drawY, width, height)
|
||||||
uiItems.forEach { it.render(batch, camera) }
|
uiItems.forEach { it.render(batch, camera) }
|
||||||
buttonReset.render(batch, camera)
|
presetSelector.render(batch, camera)
|
||||||
|
|
||||||
// title
|
// title
|
||||||
// todo show "Keyboard"/"Gamepad" accordingly
|
// todo show "Keyboard"/"Gamepad" accordingly
|
||||||
@@ -215,21 +227,56 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setControlOf(key: Int, control: Int) {
|
fun setControlOf(key: Int, control: Int) {
|
||||||
|
if (App.getConfigString("control_preset_keyboard") != "Custom") {
|
||||||
|
System.err.println("[UIKeyboardControlPanel] cannot set a control if the preset is not 'Custom' (current preset: ${App.getConfigString("control_preset_keyboard")})")
|
||||||
|
return
|
||||||
|
}
|
||||||
if (control >= 0) {
|
if (control >= 0) {
|
||||||
App.setConfig(UIItemControlPaletteBaloon.indexToConfigKey[control]!!, key)
|
val controlName = UIItemControlPaletteBaloon.indexToConfigKey[control]!!
|
||||||
|
|
||||||
|
val conflicts = App.gameConfig.keySet.filter {
|
||||||
|
(it as String).startsWith("control_key_")
|
||||||
|
}.map {
|
||||||
|
(it as String).let { it to
|
||||||
|
try { (App.getConfigInt(it) == key) }
|
||||||
|
catch (_: ClassCastException) { false }
|
||||||
|
}
|
||||||
|
}.filter { it.second }.map { it.first }.firstOrNull()
|
||||||
|
|
||||||
|
println("[UIKeyboardControlPanel] key=$key, control=$controlName")
|
||||||
|
|
||||||
|
if (conflicts != null) {
|
||||||
|
val oldValue = App.getConfigInt(controlName)
|
||||||
|
App.setConfig(conflicts, oldValue)
|
||||||
|
|
||||||
|
println("[UIKeyboardControlPanel] set config $conflicts=$oldValue")
|
||||||
|
}
|
||||||
|
|
||||||
|
App.setConfig(controlName, key)
|
||||||
|
println("[UIKeyboardControlPanel] set config $controlName=$key")
|
||||||
}
|
}
|
||||||
updateKeycaps()
|
updateKeycaps()
|
||||||
|
|
||||||
|
Terrarum.ingame?.let {
|
||||||
|
it.onConfigChange()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
super.touchDown(screenX, screenY, pointer, button)
|
super.touchDown(screenX, screenY, pointer, button)
|
||||||
buttonReset.touchDown(screenX, screenY, pointer, button)
|
presetSelector.touchDown(screenX, screenY, pointer, button)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
super.touchUp(screenX, screenY, pointer, button)
|
super.touchUp(screenX, screenY, pointer, button)
|
||||||
buttonReset.touchUp(screenX, screenY, pointer, button)
|
presetSelector.touchUp(screenX, screenY, pointer, button)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun scrolled(amountX: Float, amountY: Float): Boolean {
|
||||||
|
super.scrolled(amountX, amountY)
|
||||||
|
presetSelector.scrolled(amountX, amountY)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ class UILoadDemoSavefiles(val remoCon: UIRemoCon) : Advanceable() {
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_up"))}${getKeycapPC(App.getConfigInt("control_key_down"))}" +
|
"${getKeycapPC(ControlPresets.getKey("control_key_up"))}${getKeycapPC(ControlPresets.getKey("control_key_down"))}" +
|
||||||
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
else
|
else
|
||||||
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
@@ -408,12 +408,12 @@ class UILoadDemoSavefiles(val remoCon: UIRemoCon) : Advanceable() {
|
|||||||
if (this.isVisible) {
|
if (this.isVisible) {
|
||||||
val cells = getCells()
|
val cells = getCells()
|
||||||
|
|
||||||
if ((keycode == Input.Keys.UP || keycode == App.getConfigInt("control_key_up")) && scrollTarget > 0) {
|
if ((keycode == Input.Keys.UP || keycode == ControlPresets.getKey("control_key_up")) && scrollTarget > 0) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget -= 1
|
scrollTarget -= 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
}
|
}
|
||||||
else if ((keycode == Input.Keys.DOWN || keycode == App.getConfigInt("control_key_down")) && scrollTarget < cells.size - savesVisible) {
|
else if ((keycode == Input.Keys.DOWN || keycode == ControlPresets.getKey("control_key_down")) && scrollTarget < cells.size - savesVisible) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget += 1
|
scrollTarget += 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_up"))}${getKeycapPC(App.getConfigInt("control_key_down"))}" +
|
"${getKeycapPC(ControlPresets.getKey("control_key_up"))}${getKeycapPC(ControlPresets.getKey("control_key_down"))}" +
|
||||||
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
else
|
else
|
||||||
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
@@ -235,7 +235,7 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
|
|||||||
if (showSpinner) {
|
if (showSpinner) {
|
||||||
val spin = spinner.get(spinnerFrame % 8, spinnerFrame / 8)
|
val spin = spinner.get(spinnerFrame % 8, spinnerFrame / 8)
|
||||||
val offX = UIRemoCon.menubarOffX - UIRemoCon.UIRemoConElement.paddingLeft + 72 + 1
|
val offX = UIRemoCon.menubarOffX - UIRemoCon.UIRemoConElement.paddingLeft + 72 + 1
|
||||||
val offY = UIRemoCon.menubarOffY - UIRemoCon.UIRemoConElement.lineHeight * 3 + 16
|
val offY = UIRemoCon.menubarOffY - UIRemoCon.UIRemoConElement.lineHeight * 4 + 16
|
||||||
batch.draw(spin, offX.toFloat(), offY.toFloat())
|
batch.draw(spin, offX.toFloat(), offY.toFloat())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,12 +249,12 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
|
|||||||
if (this.isVisible) {
|
if (this.isVisible) {
|
||||||
val cells = playerCells
|
val cells = playerCells
|
||||||
|
|
||||||
if ((keycode == Input.Keys.UP || keycode == App.getConfigInt("control_key_up")) && scrollTarget > 0) {
|
if ((keycode == Input.Keys.UP || keycode == ControlPresets.getKey("control_key_up")) && scrollTarget > 0) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget -= 1
|
scrollTarget -= 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
}
|
}
|
||||||
else if ((keycode == Input.Keys.DOWN || keycode == App.getConfigInt("control_key_down")) && scrollTarget < cells.size - savesVisible) {
|
else if ((keycode == Input.Keys.DOWN || keycode == ControlPresets.getKey("control_key_down")) && scrollTarget < cells.size - savesVisible) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget += 1
|
scrollTarget += 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
|
|||||||
@@ -227,8 +227,8 @@ class UILoadManage(val full: UILoadSavegame) : UICanvas() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
MODE_DELETE -> {
|
MODE_DELETE -> {
|
||||||
Toolkit.drawTextCentered(batch, App.fontGame, Lang["MENU_LABEL_SAVE_WILL_BE_DELETED"], Toolkit.drawWidth, 0, full.titleTopGradEnd + full.cellInterval - 46)
|
Toolkit.drawTextCentered(batch, App.fontGame, Lang["MENU_LABEL_SAVE_WILL_BE_DELETED"], Toolkit.drawWidth, 0, full.titleTopGradEnd + full.cellInterval + SAVE_CELL_HEIGHT + 36)
|
||||||
Toolkit.drawTextCentered(batch, App.fontGame, Lang["MENU_LABEL_ARE_YOU_SURE"], Toolkit.drawWidth, 0, full.titleTopGradEnd + full.cellInterval + SAVE_CELL_HEIGHT + 36)
|
Toolkit.drawTextCentered(batch, App.fontGame, Lang["MENU_LABEL_ARE_YOU_SURE"], Toolkit.drawWidth, 0, full.titleTopGradEnd + full.cellInterval + SAVE_CELL_HEIGHT + 36 + 24)
|
||||||
|
|
||||||
delButtons.forEach { it.render(batch, camera) }
|
delButtons.forEach { it.render(batch, camera) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,8 +90,17 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
|||||||
listOf(NullUI/*, transitionalAutosave*/)
|
listOf(NullUI/*, transitionalAutosave*/)
|
||||||
)
|
)
|
||||||
|
|
||||||
internal fun queueUpManageScr() { transitionPanel.setCentreUIto(0) }
|
private val nodesForListing = Yaml(UITitleRemoConYaml.injectedMenuSingleCharSel).parse()
|
||||||
internal fun queueUpNewCharScr() { transitionPanel.setCentreUIto(1) }
|
private val nodesForManage = Yaml(UITitleRemoConYaml.injectedMenuSingleSaveManage).parse()
|
||||||
|
|
||||||
|
internal fun queueUpManageScr() {
|
||||||
|
transitionPanel.setCentreUIto(0)
|
||||||
|
remoCon.setNewRemoConContents(nodesForManage)
|
||||||
|
}
|
||||||
|
internal fun queueUpNewCharScr() {
|
||||||
|
transitionPanel.setCentreUIto(1)
|
||||||
|
remoCon.setNewRemoConContents(nodesForListing)
|
||||||
|
}
|
||||||
|
|
||||||
// internal fun bringAutosaveSelectorUp() { transitionPanel.setRightUIto(1) }
|
// internal fun bringAutosaveSelectorUp() { transitionPanel.setRightUIto(1) }
|
||||||
// internal fun takeAutosaveSelectorDown() { transitionPanel.setRightUIto(0) }
|
// internal fun takeAutosaveSelectorDown() { transitionPanel.setRightUIto(0) }
|
||||||
@@ -102,6 +111,10 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
|||||||
|
|
||||||
internal fun changePanelTo(index: Int) {
|
internal fun changePanelTo(index: Int) {
|
||||||
transitionPanel.requestTransition(index)
|
transitionPanel.requestTransition(index)
|
||||||
|
if (index == 1)
|
||||||
|
remoCon.setNewRemoConContents(nodesForManage)
|
||||||
|
else
|
||||||
|
remoCon.setNewRemoConContents(nodesForListing)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun advanceMode(button: UIItem) {
|
override fun advanceMode(button: UIItem) {
|
||||||
@@ -118,6 +131,9 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
|||||||
// takeAutosaveSelectorDown()
|
// takeAutosaveSelectorDown()
|
||||||
transitionPanel.show()
|
transitionPanel.show()
|
||||||
|
|
||||||
|
nodesForListing.parent = remoCon.treeRoot
|
||||||
|
nodesForManage.parent = remoCon.treeRoot
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hide() {
|
override fun hide() {
|
||||||
|
|||||||
@@ -26,11 +26,14 @@ class UIPerformanceControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
arrayOf("", { Lang["MENU_OPTIONS_GAMEPLAY"] }, "h1"),
|
arrayOf("", { Lang["MENU_OPTIONS_GAMEPLAY"] }, "h1"),
|
||||||
arrayOf("autosaveinterval", { Lang["MENU_OPTIONS_AUTOSAVE"] + " (${Lang["CONTEXT_TIME_MINUTE_PLURAL"]})" }, "spinnerimul,1,120,1,60000"),
|
arrayOf("autosaveinterval", { Lang["MENU_OPTIONS_AUTOSAVE"] + " (${Lang["CONTEXT_TIME_MINUTE_PLURAL"]})" }, "spinnerimul,1,120,1,60000"),
|
||||||
arrayOf("notificationshowuptime", { Lang["MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION"] + " (${Lang["CONTEXT_TIME_SECOND_PLURAL"]})" }, "spinnerimul,2,10,1,1000"),
|
arrayOf("notificationshowuptime", { Lang["MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION"] + " (${Lang["CONTEXT_TIME_SECOND_PLURAL"]})" }, "spinnerimul,2,10,1,1000"),
|
||||||
|
arrayOf("", { Lang["MENU_LABEL_GRAPHICS"] }, "h1"),
|
||||||
|
arrayOf("atlastexsize", { Lang["MENU_OPTIONS_ATLAS_TEXTURE_SIZE"] }, "spinnersel,1024,2048,4096,8192"),
|
||||||
arrayOf("", { Lang["MENU_LABEL_JVM_DNT"] }, "h1"),
|
arrayOf("", { Lang["MENU_LABEL_JVM_DNT"] }, "h1"),
|
||||||
arrayOf("jvm_xmx", { Lang["MENU_OPTIONS_JVM_HEAP_MAX"] + " (GB)" }, "spinner,2,32,1"),
|
arrayOf("jvm_xmx", { Lang["MENU_OPTIONS_JVM_HEAP_MAX"] + " (GB)" }, "spinner,2,32,1"),
|
||||||
arrayOf("jvm_extra_cmd", { Lang["MENU_LABEL_EXTRA_JVM_ARGUMENTS"] }, "typein"),
|
arrayOf("jvm_extra_cmd", { Lang["MENU_LABEL_EXTRA_JVM_ARGUMENTS"] }, "typein"),
|
||||||
arrayOf("", { "(${Lang["MENU_LABEL_RESTART_REQUIRED"]})" }, "p"),
|
arrayOf("", { "(${Lang["MENU_LABEL_RESTART_REQUIRED"]})" }, "p"),
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override var height = ControlPanelCommon.getMenuHeight("basegame.performancecontrolpanel")
|
override var height = ControlPanelCommon.getMenuHeight("basegame.performancecontrolpanel")
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ import kotlin.math.roundToInt
|
|||||||
* Created by minjaesong on 2016-07-20.
|
* Created by minjaesong on 2016-07-20.
|
||||||
*/
|
*/
|
||||||
class UIQuickslotBar : UICanvas() {
|
class UIQuickslotBar : UICanvas() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
handler.allowESCtoClose = false
|
||||||
|
}
|
||||||
|
|
||||||
private val cellSize = ItemSlotImageFactory.slotImage.tileW // 38
|
private val cellSize = ItemSlotImageFactory.slotImage.tileW // 38
|
||||||
|
|
||||||
private val gutter = 10 - 6 // do -6 to get a gutter size of not-enlarged cells
|
private val gutter = 10 - 6 // do -6 to get a gutter size of not-enlarged cells
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ import kotlin.math.roundToInt
|
|||||||
* Created by minjaesong on 2016-07-20.
|
* Created by minjaesong on 2016-07-20.
|
||||||
*/
|
*/
|
||||||
class UIQuickslotPie : UICanvas() {
|
class UIQuickslotPie : UICanvas() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
handler.allowESCtoClose = false
|
||||||
|
}
|
||||||
|
|
||||||
private val cellSize = ItemSlotImageFactory.slotImage.tileW
|
private val cellSize = ItemSlotImageFactory.slotImage.tileW
|
||||||
|
|
||||||
private val slotCount = UIQuickslotBar.SLOT_COUNT
|
private val slotCount = UIQuickslotBar.SLOT_COUNT
|
||||||
|
|||||||
@@ -18,10 +18,14 @@ import kotlin.math.roundToInt
|
|||||||
* Created by minjaesong on 2019-08-11.
|
* Created by minjaesong on 2019-08-11.
|
||||||
*/
|
*/
|
||||||
class UIScreenZoom : UICanvas(
|
class UIScreenZoom : UICanvas(
|
||||||
App.getConfigInt("control_key_zoom")
|
"control_key_zoom"
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val zoomText = "${getKeycapPC(handler.toggleKeyLiteral!!)} $EMDASH Zoom Out"
|
init {
|
||||||
|
handler.allowESCtoClose = false
|
||||||
|
}
|
||||||
|
|
||||||
|
val zoomText = "${getKeycapPC(handler.toggleKey!!)} $EMDASH Zoom Out"
|
||||||
|
|
||||||
override var width = App.fontGame.getWidth(zoomText)
|
override var width = App.fontGame.getWidth(zoomText)
|
||||||
override var height = App.fontGame.lineHeight.toInt()
|
override var height = App.fontGame.lineHeight.toInt()
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import kotlin.math.min
|
|||||||
* Created by minjaesong on 2019-07-08.
|
* Created by minjaesong on 2019-07-08.
|
||||||
*/
|
*/
|
||||||
internal class UIStorageChest : UICanvas(
|
internal class UIStorageChest : UICanvas(
|
||||||
toggleKeyLiteral = App.getConfigInt("control_key_inventory"),
|
toggleKeyLiteral = "control_key_inventory",
|
||||||
toggleButtonLiteral = App.getConfigInt("control_gamepad_start"),
|
toggleButtonLiteral = "control_gamepad_start",
|
||||||
), HasInventory {
|
), HasInventory {
|
||||||
|
|
||||||
lateinit var chestInventory: FixtureInventory
|
lateinit var chestInventory: FixtureInventory
|
||||||
@@ -175,7 +175,7 @@ internal class UIStorageChest : UICanvas(
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
else
|
else
|
||||||
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]} "
|
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]} "
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class UITierOneWatch() : UICanvas() {
|
|||||||
ELuptimer += delta
|
ELuptimer += delta
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouseUp || Gdx.input.isKeyPressed(App.getConfigInt("control_key_interact"))) {
|
if (mouseUp || Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_interact"))) {
|
||||||
ELuptimer = 0f
|
ELuptimer = 0f
|
||||||
ELon = true
|
ELon = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class UITitleModules(val remoCon: UIRemoCon) : UICanvas() {
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_up"))}${getKeycapPC(App.getConfigInt("control_key_down"))}" +
|
"${getKeycapPC(ControlPresets.getKey("control_key_up"))}${getKeycapPC(ControlPresets.getKey("control_key_down"))}" +
|
||||||
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
else
|
else
|
||||||
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
@@ -206,12 +206,12 @@ class UITitleModules(val remoCon: UIRemoCon) : UICanvas() {
|
|||||||
|
|
||||||
override fun keyDown(keycode: Int): Boolean {
|
override fun keyDown(keycode: Int): Boolean {
|
||||||
if (this.isVisible) {
|
if (this.isVisible) {
|
||||||
if ((keycode == Input.Keys.UP || keycode == App.getConfigInt("control_key_up")) && scrollTarget > 0) {
|
if ((keycode == Input.Keys.UP || keycode == ControlPresets.getKey("control_key_up")) && scrollTarget > 0) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget -= 1
|
scrollTarget -= 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
}
|
}
|
||||||
else if ((keycode == Input.Keys.DOWN || keycode == App.getConfigInt("control_key_down")) && scrollTarget < moduleCells.size - savesVisible) {
|
else if ((keycode == Input.Keys.DOWN || keycode == ControlPresets.getKey("control_key_down")) && scrollTarget < moduleCells.size - savesVisible) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget += 1
|
scrollTarget += 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ object UITitleRemoConYaml {
|
|||||||
|
|
||||||
// todo add MENU_IO_IMPORT
|
// todo add MENU_IO_IMPORT
|
||||||
val injectedMenuSingleCharSel = """
|
val injectedMenuSingleCharSel = """
|
||||||
|
- MENU_IO_IMPORT : net.torvald.terrarum.modulebasegame.ui.UIImportAvatar
|
||||||
- CONTEXT_CHARACTER_NEW : net.torvald.terrarum.modulebasegame.ui.UINewCharacter
|
- CONTEXT_CHARACTER_NEW : net.torvald.terrarum.modulebasegame.ui.UINewCharacter
|
||||||
- MENU_LABEL_RETURN
|
- MENU_LABEL_RETURN
|
||||||
"""
|
"""
|
||||||
@@ -48,6 +49,12 @@ object UITitleRemoConYaml {
|
|||||||
val injectedMenuSingleWorldSel = """
|
val injectedMenuSingleWorldSel = """
|
||||||
- CONTEXT_WORLD_NEW : net.torvald.terrarum.modulebasegame.ui.UINewWorld
|
- CONTEXT_WORLD_NEW : net.torvald.terrarum.modulebasegame.ui.UINewWorld
|
||||||
- MENU_LABEL_RETURN
|
- MENU_LABEL_RETURN
|
||||||
|
"""
|
||||||
|
|
||||||
|
val injectedMenuSingleSaveManage = """
|
||||||
|
- MENU_MODULES
|
||||||
|
- MENU_LABEL_PREV_SAVES
|
||||||
|
- MENU_LABEL_RETURN
|
||||||
"""
|
"""
|
||||||
|
|
||||||
operator fun invoke(hasSave: Boolean) =
|
operator fun invoke(hasSave: Boolean) =
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ import net.torvald.terrarum.ui.UICanvas
|
|||||||
*/
|
*/
|
||||||
class UITooltip : UICanvas() {
|
class UITooltip : UICanvas() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
handler.allowESCtoClose = false
|
||||||
|
}
|
||||||
|
|
||||||
override var openCloseTime: Second = 0f
|
override var openCloseTime: Second = 0f
|
||||||
|
|
||||||
private val tooltipBackCol = Color.WHITE
|
private val tooltipBackCol = Color.WHITE
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ class UIVitalMetre(
|
|||||||
val order: Int
|
val order: Int
|
||||||
) : UICanvas() {
|
) : UICanvas() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
handler.allowESCtoClose = false
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// semitransparent
|
// semitransparent
|
||||||
color?.a = 0.91f
|
color?.a = 0.91f
|
||||||
|
|||||||
382
src/net/torvald/terrarum/modulebasegame/ui/UIWallCalendar.kt
Normal file
382
src/net/torvald/terrarum/modulebasegame/ui/UIWallCalendar.kt
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.ui
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Camera
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.gameworld.WorldTime
|
||||||
|
import net.torvald.terrarum.gameworld.WorldTime.Companion.MONTH_LENGTH
|
||||||
|
import net.torvald.terrarum.langpack.Lang
|
||||||
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
|
import net.torvald.unicode.getKeycapPC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-15.
|
||||||
|
*/
|
||||||
|
class UIWallCalendar : UICanvas(
|
||||||
|
toggleKeyLiteral = "control_key_inventory",
|
||||||
|
toggleButtonLiteral = "control_gamepad_start",
|
||||||
|
) {
|
||||||
|
private val yearCellWidth = 200
|
||||||
|
private val cellWidth = 80
|
||||||
|
private val cellHeight = 24
|
||||||
|
|
||||||
|
override var width: Int = Toolkit.drawWidth
|
||||||
|
override var height: Int = App.scr.height
|
||||||
|
|
||||||
|
private val y = UIInventoryFull.INVENTORY_CELLS_OFFSET_Y() + 1 - 34
|
||||||
|
|
||||||
|
private val drawStartX = (Toolkit.drawWidth - cellWidth * 8) / 2 - 4
|
||||||
|
private val cellsStartY = y + 34
|
||||||
|
|
||||||
|
private val SP = "\u3000 "
|
||||||
|
val controlHelp: String
|
||||||
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
|
else
|
||||||
|
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
|
|
||||||
|
|
||||||
|
private var todayCell = -1
|
||||||
|
|
||||||
|
private val cellBackCols = listOf(
|
||||||
|
Color(0x3f1e22_C8), // OKLCh 14, 5, 18
|
||||||
|
Color(0x022f3a_C8), // OKLCh 218, 5, 18
|
||||||
|
Color(0x2d2b09_C8), // OKLCh 105, 5, 18
|
||||||
|
Color(0x252934_C8) // OKLCh 265, 2, 18
|
||||||
|
)
|
||||||
|
private val seasonMarkers = listOf(
|
||||||
|
7 to "CONTEXT_CALENDAR_SEASON_SPRING",
|
||||||
|
39 to "CONTEXT_CALENDAR_SEASON_SUMMER",
|
||||||
|
71 to "CONTEXT_CALENDAR_SEASON_AUTUMN",
|
||||||
|
103 to "CONTEXT_CALENDAR_SEASON_WINTER"
|
||||||
|
)
|
||||||
|
|
||||||
|
private var mouseOverCell = -1
|
||||||
|
private var mouseOverSeason = -1
|
||||||
|
|
||||||
|
override fun updateUI(delta: Float) {
|
||||||
|
mouseOverCell = if (relativeMouseX in drawStartX until drawStartX + 8 * (cellWidth + 1) &&
|
||||||
|
relativeMouseY in cellsStartY - 1 until cellsStartY - 1 + 17 * (cellHeight + 3)) {
|
||||||
|
|
||||||
|
val x = (relativeMouseX - drawStartX) / (cellWidth + 1)
|
||||||
|
val y = (relativeMouseY - cellsStartY + 1) / (cellHeight + 3)
|
||||||
|
|
||||||
|
// disable highlighting on invalid date (verddag and not winter 30)
|
||||||
|
if (x == 7 && y < 16) -1
|
||||||
|
else y * 8 + x
|
||||||
|
}
|
||||||
|
else -1
|
||||||
|
|
||||||
|
mouseOverSeason = when (mouseOverCell) {
|
||||||
|
-1 -> -1
|
||||||
|
in 0 until 34 -> 0
|
||||||
|
in 34 until 68 -> 1
|
||||||
|
in 68 until 102 -> 2
|
||||||
|
else -> 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||||
|
UIInventoryFull.drawBackground(batch, 1f)
|
||||||
|
|
||||||
|
val thisYear = INGAME.world.worldTime.years
|
||||||
|
val today = INGAME.world.worldTime.ordinalDay + 1
|
||||||
|
val todayOfWeek = INGAME.world.worldTime.dayOfWeek
|
||||||
|
|
||||||
|
// cell background
|
||||||
|
batch.color = Toolkit.Theme.COL_CELL_FILL
|
||||||
|
Toolkit.fillArea(batch, (width - yearCellWidth) / 2, y - 34, yearCellWidth, 24)
|
||||||
|
for (week in 0..7) {
|
||||||
|
Toolkit.fillArea(batch, drawStartX + (cellWidth + 1) * week + 1, y, cellWidth - 2, 24)
|
||||||
|
}
|
||||||
|
for (cellNum in 0 until 17 * 8) {
|
||||||
|
batch.color = when (cellNum) {
|
||||||
|
in 0 until 34 -> cellBackCols[0]
|
||||||
|
in 34 until 68 -> cellBackCols[1]
|
||||||
|
in 68 until 102 -> cellBackCols[2]
|
||||||
|
else -> cellBackCols[3]
|
||||||
|
}
|
||||||
|
if (cellNum % 8 != 7 || cellNum == 17 * 8 - 1) {
|
||||||
|
Toolkit.fillArea(batch, drawStartX + (cellWidth + 1) * (cellNum % 8) + 1, cellsStartY + (cellHeight + 3) * (cellNum / 8), cellWidth - 2, cellHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// season name cell background
|
||||||
|
for (k in 0..3) {
|
||||||
|
batch.color = cellBackCols[k]
|
||||||
|
Toolkit.fillArea(batch, drawStartX + (cellWidth + 1) * 7 + 1, cellsStartY + (cellHeight + 3) * (k * 4), cellWidth - 2, (cellHeight + 3) * 4 - 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// cell border
|
||||||
|
batch.color = Toolkit.Theme.COL_INACTIVE
|
||||||
|
Toolkit.drawBoxBorder(batch, (width - yearCellWidth) / 2 - 1, y - 35, yearCellWidth + 2, 26)
|
||||||
|
Toolkit.drawBoxBorder(batch, drawStartX, y - 1, 8 * (cellWidth + 1) - 1, 26)
|
||||||
|
for (week in 0..7) {
|
||||||
|
Toolkit.drawBoxBorder(batch, drawStartX + (cellWidth + 1) * week, y - 1, cellWidth, 26)
|
||||||
|
}
|
||||||
|
// highlight a day name of mouse-up
|
||||||
|
batch.color = Toolkit.Theme.COL_MOUSE_UP
|
||||||
|
if (mouseOverCell >= 0) Toolkit.drawBoxBorder(batch, drawStartX + (cellWidth + 1) * (mouseOverCell % 8), y - 1, cellWidth, 26)
|
||||||
|
// highlight today's week name
|
||||||
|
batch.color = Toolkit.Theme.COL_SELECTED
|
||||||
|
Toolkit.drawBoxBorder(batch, drawStartX + (cellWidth + 1) * todayOfWeek, y - 1, cellWidth, 26)
|
||||||
|
|
||||||
|
|
||||||
|
// draw days grid
|
||||||
|
batch.color = Toolkit.Theme.COL_INACTIVE
|
||||||
|
Toolkit.drawBoxBorder(batch, drawStartX, cellsStartY - 1, 8 * (cellWidth + 1) - 1, 17 * (cellHeight + 3) - 1)
|
||||||
|
// non-season-name-cells
|
||||||
|
for (cellNum in 0 until 17 * 8) {
|
||||||
|
if (cellNum % 8 != 7 || cellNum == 17 * 8 - 1) {
|
||||||
|
Toolkit.drawBoxBorder(batch, drawStartX + (cellWidth + 1) * (cellNum % 8), cellsStartY + (cellHeight + 3) * (cellNum / 8) - 1, cellWidth, cellHeight + 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// season-name-cells
|
||||||
|
for (k in 0..3) {
|
||||||
|
Toolkit.drawBoxBorder(batch, drawStartX + (cellWidth + 1) * 7, cellsStartY + (cellHeight + 3) * (k * 4) - 1, cellWidth, (cellHeight + 3) * 4 - 1)
|
||||||
|
}
|
||||||
|
// highlight a day of mouse-up
|
||||||
|
batch.color = Toolkit.Theme.COL_MOUSE_UP
|
||||||
|
if (mouseOverCell >= 0) Toolkit.drawBoxBorder(batch, drawStartX + (cellWidth + 1) * (mouseOverCell % 8), cellsStartY + (cellHeight + 3) * (mouseOverCell / 8) - 1, cellWidth, cellHeight + 2)
|
||||||
|
|
||||||
|
|
||||||
|
// season border
|
||||||
|
batch.color = Toolkit.Theme.COL_MOUSE_UP
|
||||||
|
if (mouseOverSeason == 0) {
|
||||||
|
Toolkit.drawStraightLine(batch,
|
||||||
|
drawStartX,
|
||||||
|
cellsStartY - 2,
|
||||||
|
drawStartX + (cellWidth + 1) * 8 - 1,
|
||||||
|
1,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX - 1,
|
||||||
|
cellsStartY - 1,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 5 - 3,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX + (cellWidth + 1) * 8 - 1,
|
||||||
|
cellsStartY - 1,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 4 - 3,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (mouseOverSeason in 0..1) {
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 5 - 3,
|
||||||
|
drawStartX + (cellWidth + 1) * 2 - 1,
|
||||||
|
1,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX + (cellWidth + 1) * 2 - 1,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 4 - 2,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 5 - 3,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX + (cellWidth + 1) * 2,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 4 - 3,
|
||||||
|
drawStartX + (cellWidth + 1) * 8 - 1,
|
||||||
|
1,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (mouseOverSeason == 1) {
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX - 1,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 5 - 2,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 9 - 3,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX + (cellWidth + 1) * 8 - 1,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 4 - 2,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 8 - 3,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (mouseOverSeason in 1..2) {
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 9 - 3,
|
||||||
|
drawStartX + (cellWidth + 1) * 4 - 1,
|
||||||
|
1,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX + (cellWidth + 1) * 4 - 1,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 8 - 2,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 9 - 3,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX + (cellWidth + 1) * 4,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 8 - 3,
|
||||||
|
drawStartX + (cellWidth + 1) * 8 - 1,
|
||||||
|
1,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (mouseOverSeason == 2) {
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX - 1,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 9 - 2,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 13 - 3,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX + (cellWidth + 1) * 8 - 1,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 8 - 2,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 12 - 3,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (mouseOverSeason in 2..3) {
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 13 - 3,
|
||||||
|
drawStartX + (cellWidth + 1) * 6 - 1,
|
||||||
|
1,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX + (cellWidth + 1) * 6 - 1,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 12 - 2,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 13 - 3,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX + (cellWidth + 1) * 6,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 12 - 3,
|
||||||
|
drawStartX + (cellWidth + 1) * 8 - 1,
|
||||||
|
1,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (mouseOverSeason == 3) {
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX - 1,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 13 - 2,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 17 - 3,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(
|
||||||
|
batch,
|
||||||
|
drawStartX + (cellWidth + 1) * 8 - 1,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 12 - 2,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 17 - 3,
|
||||||
|
1,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
Toolkit.drawStraightLine(batch,
|
||||||
|
drawStartX,
|
||||||
|
cellsStartY + 1 + (cellHeight + 3) * 17 - 3,
|
||||||
|
drawStartX + (cellWidth + 1) * 8 - 1,
|
||||||
|
1,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// cell texts
|
||||||
|
batch.color = Toolkit.Theme.COL_LIST_DEFAULT
|
||||||
|
Toolkit.drawTextCentered(batch, App.fontGame, Lang.getAndUseTemplate("CONTEXT_CALENDAR_DATE_FORMAT_Y", false, thisYear), yearCellWidth, (width - yearCellWidth) / 2, y - 34)
|
||||||
|
for (week in 0..7) {
|
||||||
|
// highlight this week and the mouse-up
|
||||||
|
batch.color = if (week == todayOfWeek) Toolkit.Theme.COL_SELECTED else if (week == mouseOverCell % 8) Toolkit.Theme.COL_MOUSE_UP else Toolkit.Theme.COL_LIST_DEFAULT
|
||||||
|
|
||||||
|
val t = WorldTime.getDayName(week)
|
||||||
|
val tlen = App.fontGame.getWidth(t)
|
||||||
|
App.fontGame.draw(batch, t, drawStartX + (cellWidth + 1) * week + (cellWidth - tlen) / 2, y)
|
||||||
|
}
|
||||||
|
var dayAkku = 1
|
||||||
|
for (cellNum in 0 until 17 * 8) {
|
||||||
|
val day = if (cellNum == 17*8-1) 120 else if (cellNum % 8 == 7) 0 else dayAkku
|
||||||
|
|
||||||
|
if (day > 0) {
|
||||||
|
// highlight today and the mouse-up
|
||||||
|
batch.color = if (day == today) Toolkit.Theme.COL_SELECTED else if (cellNum == mouseOverCell) Toolkit.Theme.COL_MOUSE_UP else Toolkit.Theme.COL_LIST_DEFAULT
|
||||||
|
|
||||||
|
val t = "${(day % MONTH_LENGTH).let { if (it == 0) MONTH_LENGTH else it }}".padStart(2, '\u2007')
|
||||||
|
App.fontGame.draw(batch, t, drawStartX + (cellWidth + 1) * (cellNum % 8) - 20 + cellWidth - 4, cellsStartY + (cellHeight + 3) * (cellNum / 8))
|
||||||
|
|
||||||
|
if (day == today) todayCell = cellNum
|
||||||
|
|
||||||
|
dayAkku += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// draw seasonal names
|
||||||
|
seasonMarkers.forEachIndexed { index, (cellNum, key) ->
|
||||||
|
batch.color = if (index == mouseOverSeason) Toolkit.Theme.COL_MOUSE_UP else Toolkit.Theme.COL_INACTIVE
|
||||||
|
Toolkit.drawTextCentered(batch, App.fontGame, Lang[key], cellWidth, drawStartX + (cellWidth + 1) * (cellNum % 8), cellsStartY + (cellHeight + 3) * (cellNum / 8) + ((cellHeight + 3) * 1.5f).floorToInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
// highlight today cell
|
||||||
|
if (todayCell >= 0) {
|
||||||
|
batch.color = Toolkit.Theme.COL_SELECTED
|
||||||
|
Toolkit.drawBoxBorder(batch, drawStartX + (cellWidth + 1) * (todayCell % 8), cellsStartY + (cellHeight + 3) * (todayCell / 8) - 1, cellWidth, cellHeight + 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// control hints
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
App.fontGame.draw(batch, controlHelp, drawStartX + 2, cellsStartY+ 17 * (cellHeight + 3) + 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doOpening(delta: Float) {
|
||||||
|
super.doOpening(delta)
|
||||||
|
INGAME.pause()
|
||||||
|
INGAME.setTooltipMessage(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doClosing(delta: Float) {
|
||||||
|
super.doClosing(delta)
|
||||||
|
INGAME.resume()
|
||||||
|
INGAME.setTooltipMessage(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun endOpening(delta: Float) {
|
||||||
|
super.endOpening(delta)
|
||||||
|
UIItemInventoryItemGrid.tooltipShowing.clear()
|
||||||
|
INGAME.setTooltipMessage(null) // required!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun endClosing(delta: Float) {
|
||||||
|
super.endClosing(delta)
|
||||||
|
UIItemInventoryItemGrid.tooltipShowing.clear()
|
||||||
|
INGAME.setTooltipMessage(null) // required!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.ui
|
package net.torvald.terrarum.modulebasegame.ui
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Camera
|
import com.badlogic.gdx.graphics.Camera
|
||||||
import com.badlogic.gdx.graphics.Color
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
@@ -31,8 +30,8 @@ import java.util.UUID
|
|||||||
* Created by minjaesong on 2023-05-19.
|
* Created by minjaesong on 2023-05-19.
|
||||||
*/
|
*/
|
||||||
class UIWorldPortal : UICanvas(
|
class UIWorldPortal : UICanvas(
|
||||||
toggleKeyLiteral = App.getConfigInt("control_key_inventory"),
|
toggleKeyLiteral = "control_key_inventory",
|
||||||
toggleButtonLiteral = App.getConfigInt("control_gamepad_start"),
|
toggleButtonLiteral = "control_gamepad_start",
|
||||||
) {
|
) {
|
||||||
|
|
||||||
override var width: Int = Toolkit.drawWidth
|
override var width: Int = Toolkit.drawWidth
|
||||||
@@ -54,7 +53,7 @@ class UIWorldPortal : UICanvas(
|
|||||||
private val SP = "\u3000 "
|
private val SP = "\u3000 "
|
||||||
val portalListingControlHelp: String
|
val portalListingControlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
else
|
else
|
||||||
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]}" +
|
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]}" +
|
||||||
"$SP${App.gamepadLabelLT} ${Lang["GAME_WORLD_SEARCH"]}" +
|
"$SP${App.gamepadLabelLT} ${Lang["GAME_WORLD_SEARCH"]}" +
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ class UIWorldPortalCargo(val full: UIWorldPortal) : UICanvas(), HasInventory {
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
else
|
else
|
||||||
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]} "
|
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]} "
|
||||||
|
|
||||||
|
|||||||
@@ -4,27 +4,26 @@ import net.torvald.terrarum.savegame.toBigEndian
|
|||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
|
|
||||||
/**
|
/** My own string set that:
|
||||||
* Ascii85 implementation with my own character table based on RFC 1924. Will NOT truncate '00000' into something else;
|
* - no "/": avoids nonstandard JSON comment key which GDX will happily parse away
|
||||||
* just gzip the inputstream instead!
|
* - no "\": you know what I mean\\intention
|
||||||
|
* - no "$": avoids Kotlin string template
|
||||||
|
* - no "[{]},": even the dumbest parser can comprehend the output
|
||||||
*/
|
*/
|
||||||
object Ascii85 {
|
open class Ascii85Codec(private val CHAR_TABLE: String = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#%&'()*+-.:;<=>?@^_`|~") {
|
||||||
/** My own string set that:
|
init {
|
||||||
* - no "/": avoids nonstandard JSON comment key which GDX will happily parse away
|
if (CHAR_TABLE.length != 85) throw IllegalArgumentException("CHAR_TABLE is not 85 chars long")
|
||||||
* - no "\": you know what I mean\\intention
|
}
|
||||||
* - no "$": avoids Kotlin string template
|
|
||||||
* - no "[{]},": even the dumbest parser can comprehend the output
|
|
||||||
*/
|
|
||||||
private const val CHAR_TABLE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#%&'()*+-.:;<=>?@^_`|~"
|
|
||||||
/** As per Adobe standard */
|
/** As per Adobe standard */
|
||||||
//private val CHAR_TABLE = (33 until (33+85)).toList().map { it.toChar() }.joinToString("") // testing only!
|
//private val CHAR_TABLE = (33 until (33+85)).toList().map { it.toChar() }.joinToString("") // testing only!
|
||||||
|
|
||||||
private val INVERSE_TABLE = LongArray(127)
|
private val INVERSE_TABLE = LongArray(127)
|
||||||
|
|
||||||
/** Int of `-1` */
|
/** Int of `-1` */
|
||||||
const val PAD_BYTE = -1
|
val PAD_BYTE = -1
|
||||||
/** Null-character (`\0`) */
|
/** Null-character (`\0`) */
|
||||||
const val PAD_CHAR = 0.toChar()
|
val PAD_CHAR = 0.toChar()
|
||||||
|
|
||||||
private val INTERNAL_PAD_BYTE = 0
|
private val INTERNAL_PAD_BYTE = 0
|
||||||
private val INTERNAL_PAD_CHAR = CHAR_TABLE.last()
|
private val INTERNAL_PAD_CHAR = CHAR_TABLE.last()
|
||||||
@@ -97,10 +96,10 @@ object Ascii85 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val sum = (INVERSE_TABLE[s1.toInt()] * 52200625) +
|
val sum = (INVERSE_TABLE[s1.toInt()] * 52200625) +
|
||||||
(INVERSE_TABLE[s2.toInt()] * 614125) +
|
(INVERSE_TABLE[s2.toInt()] * 614125) +
|
||||||
(INVERSE_TABLE[s3.toInt()] * 7225) +
|
(INVERSE_TABLE[s3.toInt()] * 7225) +
|
||||||
(INVERSE_TABLE[s4.toInt()] * 85) +
|
(INVERSE_TABLE[s4.toInt()] * 85) +
|
||||||
INVERSE_TABLE[s5.toInt()]
|
INVERSE_TABLE[s5.toInt()]
|
||||||
return ByteArray(4 - padLen) { sum.ushr((3 - it) * 8).and(255).toByte() }
|
return ByteArray(4 - padLen) { sum.ushr((3 - it) * 8).and(255).toByte() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,6 +136,12 @@ object Ascii85 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ascii85 implementation with my own character table based on RFC 1924. Will NOT truncate '00000' into something else;
|
||||||
|
* just gzip the inputstream instead!
|
||||||
|
*/
|
||||||
|
object Ascii85 : Ascii85Codec()
|
||||||
|
|
||||||
fun UUID.toAscii85() =
|
fun UUID.toAscii85() =
|
||||||
Ascii85.encodeBytes(this.mostSignificantBits.toBigEndian() + this.leastSignificantBits.toBigEndian())
|
Ascii85.encodeBytes(this.mostSignificantBits.toBigEndian() + this.leastSignificantBits.toBigEndian())
|
||||||
fun String.ascii85toUUID(): UUID {
|
fun String.ascii85toUUID(): UUID {
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
App.fontSmallNumbers.draw(batch, "${if (player.jumping) "$ccG" else "$ccK"}JM", gap + 7f*(jX + 8), line(jY))
|
App.fontSmallNumbers.draw(batch, "${if (player.jumping) "$ccG" else "$ccK"}JM", gap + 7f*(jX + 8), line(jY))
|
||||||
App.fontSmallNumbers.draw(batch, "${if (player.isJumpDown) "$ccG" else "$ccK"}KY", gap + 7f*(jX + 8), line(jY+1))
|
App.fontSmallNumbers.draw(batch, "${if (player.isJumpDown) "$ccG" else "$ccK"}KY", gap + 7f*(jX + 8), line(jY+1))
|
||||||
|
|
||||||
App.fontSmallNumbers.draw(batch, "${if (player.downDownVirtually) "$ccG" else "$ccK"}$ARROW_DOWN", gap + 7f*(jX + 11), line(jY+1))
|
App.fontSmallNumbers.draw(batch, "${if (player.downButtonHeld > 0) "$ccG" else "$ccK"}$ARROW_DOWN", gap + 7f*(jX + 11), line(jY+1))
|
||||||
|
|
||||||
App.fontSmallNumbers.draw(batch, "$WIDTH$ccG${player.hitbox.width.toString().padEnd(5).substring(0,5).trim()}$ccY$HEIGHT$ccG${player.hitbox.height.toString().padEnd(5).substring(0,5)}", gap + 7f*(jX + 13), line(jY))
|
App.fontSmallNumbers.draw(batch, "$WIDTH$ccG${player.hitbox.width.toString().padEnd(5).substring(0,5).trim()}$ccY$HEIGHT$ccG${player.hitbox.height.toString().padEnd(5).substring(0,5)}", gap + 7f*(jX + 13), line(jY))
|
||||||
App.fontSmallNumbers.draw(batch, "$MASS$ccG${player.mass.toString().padEnd(8).substring(0,8)}", gap + 7f*(jX + 13), line(jY+1))
|
App.fontSmallNumbers.draw(batch, "$MASS$ccG${player.mass.toString().padEnd(8).substring(0,8)}", gap + 7f*(jX + 13), line(jY+1))
|
||||||
@@ -199,7 +199,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
val soldeg = WeatherMixer.forceSolarElev ?: world?.worldTime?.solarElevationDeg
|
val soldeg = WeatherMixer.forceSolarElev ?: world?.worldTime?.solarElevationDeg
|
||||||
val soldegStr = (soldeg ?: 0.0).toIntAndFrac(3,2)
|
val soldegStr = (soldeg ?: 0.0).toIntAndFrac(3,2)
|
||||||
val soldegNeg = ((soldeg ?: 0.0) >= 0.0).toInt()
|
val soldegNeg = ((soldeg ?: 0.0) >= 0.0).toInt()
|
||||||
val turbidity = WeatherMixer.forceTurbidity ?: WeatherMixer.turbidity
|
val turbidity = (WeatherMixer.forceTurbidity ?: WeatherMixer.turbidity).toIntAndFrac(1, 4)
|
||||||
|
|
||||||
val soldegCol = if (WeatherMixer.forceSolarElev != null) ccO else ccG
|
val soldegCol = if (WeatherMixer.forceSolarElev != null) ccO else ccG
|
||||||
val turbCol = if (WeatherMixer.forceTurbidity != null) ccO else ccG
|
val turbCol = if (WeatherMixer.forceTurbidity != null) ccO else ccG
|
||||||
@@ -292,15 +292,17 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
|
|
||||||
if (ingame != null) {
|
if (ingame != null) {
|
||||||
App.fontSmallNumbers.draw(batch, "${ccY}Actors total $ccG${ingame!!.actorContainerActive.size + ingame!!.actorContainerInactive.size}",
|
App.fontSmallNumbers.draw(batch, "${ccY}Actors total $ccG${ingame!!.actorContainerActive.size + ingame!!.actorContainerInactive.size}",
|
||||||
TinyAlphNum.W * 2f, App.scr.height - TinyAlphNum.H * 2f)
|
TinyAlphNum.W * 2f, App.scr.height - TinyAlphNum.H * 2f)
|
||||||
App.fontSmallNumbers.draw(batch, "${ccY}Active $ccG${ingame!!.actorContainerActive.size}",
|
App.fontSmallNumbers.draw(batch, "${ccY}Active $ccG${ingame!!.actorContainerActive.size}",
|
||||||
(TinyAlphNum.W * 2 + 17 * 8).toFloat(), App.scr.height - TinyAlphNum.H * 2f)
|
TinyAlphNum.W * 2f + (17 * 8), App.scr.height - TinyAlphNum.H * 2f)
|
||||||
App.fontSmallNumbers.draw(batch, "${ccY}Dormant $ccG${ingame!!.actorContainerInactive.size}",
|
App.fontSmallNumbers.draw(batch, "${ccY}Dormant $ccG${ingame!!.actorContainerInactive.size}",
|
||||||
(TinyAlphNum.W * 2 + 28 * 8).toFloat(), App.scr.height - TinyAlphNum.H * 2f)
|
TinyAlphNum.W * 2f + (28 * 8), App.scr.height - TinyAlphNum.H * 2f)
|
||||||
if (ingame is TerrarumIngame) {
|
if (ingame is TerrarumIngame) {
|
||||||
App.fontSmallNumbers.draw(batch, "${ccM}Particles $ccG${(ingame as TerrarumIngame).particlesActive}",
|
App.fontSmallNumbers.draw(batch, "${ccM}Particles $ccG${(ingame as TerrarumIngame).particlesActive}$ccY/$ccG${(ingame as TerrarumIngame).PARTICLES_MAX}",
|
||||||
(TinyAlphNum.W * 2 + 41 * 8).toFloat(), App.scr.height - TinyAlphNum.H * 2f)
|
TinyAlphNum.W * 2f, App.scr.height - TinyAlphNum.H * 4f)
|
||||||
}
|
}
|
||||||
|
App.fontSmallNumbers.draw(batch, "${ccM}Clouds $ccG${WeatherMixer.cloudsSpawned}$ccY/$ccG${WeatherMixer.cloudSpawnMax}",
|
||||||
|
TinyAlphNum.W * 2f + (18 * 8), App.scr.height - TinyAlphNum.H * 4f)
|
||||||
}
|
}
|
||||||
|
|
||||||
App.fontSmallNumbers.draw(batch, "${ccY}Actors rendering $ccG${IngameRenderer.renderingActorsCount}",
|
App.fontSmallNumbers.draw(batch, "${ccY}Actors rendering $ccG${IngameRenderer.renderingActorsCount}",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import com.badlogic.gdx.graphics.*
|
|||||||
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import com.badlogic.gdx.graphics.glutils.FloatFrameBuffer
|
import com.badlogic.gdx.graphics.glutils.Float16FrameBuffer
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
@@ -48,9 +48,9 @@ object Toolkit : Disposable {
|
|||||||
private val shaderBoxDown = App.loadShaderFromClasspath("shaders/default.vert", "shaders/boxdown.frag")
|
private val shaderBoxDown = App.loadShaderFromClasspath("shaders/default.vert", "shaders/boxdown.frag")
|
||||||
private val shaderBoxUp = App.loadShaderFromClasspath("shaders/default.vert", "shaders/boxup.frag")
|
private val shaderBoxUp = App.loadShaderFromClasspath("shaders/default.vert", "shaders/boxup.frag")
|
||||||
|
|
||||||
private lateinit var fboBlur: FloatFrameBuffer
|
private lateinit var fboBlur: Float16FrameBuffer
|
||||||
private lateinit var fboBlurHalf: FloatFrameBuffer
|
private lateinit var fboBlurHalf: Float16FrameBuffer
|
||||||
private lateinit var fboBlurQuarter: FloatFrameBuffer
|
private lateinit var fboBlurQuarter: Float16FrameBuffer
|
||||||
private lateinit var blurWriteQuad: Mesh
|
private lateinit var blurWriteQuad: Mesh
|
||||||
private lateinit var blurWriteQuad2: Mesh
|
private lateinit var blurWriteQuad2: Mesh
|
||||||
private lateinit var blurWriteQuad4: Mesh
|
private lateinit var blurWriteQuad4: Mesh
|
||||||
@@ -326,17 +326,17 @@ object Toolkit : Disposable {
|
|||||||
val fw = App.scr.width//MathUtils.nextPowerOfTwo(App.scr.width)
|
val fw = App.scr.width//MathUtils.nextPowerOfTwo(App.scr.width)
|
||||||
val fh = App.scr.height//MathUtils.nextPowerOfTwo(App.scr.height)
|
val fh = App.scr.height//MathUtils.nextPowerOfTwo(App.scr.height)
|
||||||
|
|
||||||
fboBlur = FloatFrameBuffer(
|
fboBlur = Float16FrameBuffer(
|
||||||
fw,
|
fw,
|
||||||
fh,
|
fh,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
fboBlurHalf = FloatFrameBuffer(
|
fboBlurHalf = Float16FrameBuffer(
|
||||||
fw / 2,
|
fw / 2,
|
||||||
fh / 2,
|
fh / 2,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
fboBlurQuarter = FloatFrameBuffer(
|
fboBlurQuarter = Float16FrameBuffer(
|
||||||
fw / 4,
|
fw / 4,
|
||||||
fh / 4,
|
fh / 4,
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ import kotlin.math.roundToInt
|
|||||||
* Created by minjaesong on 2015-12-31.
|
* Created by minjaesong on 2015-12-31.
|
||||||
*/
|
*/
|
||||||
abstract class UICanvas(
|
abstract class UICanvas(
|
||||||
toggleKeyLiteral: Int? = null, toggleButtonLiteral: Int? = null,
|
toggleKeyLiteral: String? = null, toggleButtonLiteral: String? = null,
|
||||||
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
||||||
customPositioning: Boolean = false, // mainly used by vital meter
|
customPositioning: Boolean = false, // mainly used by vital meter
|
||||||
doNotWarnConstant: Boolean = false
|
doNotWarnConstant: Boolean = false
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.Color
|
|||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.ControlPresets
|
||||||
import net.torvald.terrarum.FlippingSpriteBatch
|
import net.torvald.terrarum.FlippingSpriteBatch
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
@@ -25,12 +26,12 @@ import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
|||||||
* Created by minjaesong on 2015-12-31.
|
* Created by minjaesong on 2015-12-31.
|
||||||
*/
|
*/
|
||||||
class UIHandler(//var UI: UICanvas,
|
class UIHandler(//var UI: UICanvas,
|
||||||
var toggleKeyLiteral: Int? = null,
|
var toggleKeyLiteral: String? = null, // string key of the config
|
||||||
var toggleButtonLiteral: Int? = null,
|
var toggleButtonLiteral: String? = null, // string key of the config
|
||||||
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
||||||
var customPositioning: Boolean = false, // mainly used by vital meter
|
var customPositioning: Boolean = false, // mainly used by vital meter
|
||||||
var doNotWarnConstant: Boolean = false,
|
var doNotWarnConstant: Boolean = false,
|
||||||
internal var allowESCtoClose: Boolean = false,
|
internal var allowESCtoClose: Boolean = true,
|
||||||
var uiTogglerFunctionDefault: ((UIHandler) -> Unit)? = null
|
var uiTogglerFunctionDefault: ((UIHandler) -> Unit)? = null
|
||||||
): Disposable {
|
): Disposable {
|
||||||
|
|
||||||
@@ -130,12 +131,13 @@ void main() {
|
|||||||
//UI.handler = this
|
//UI.handler = this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ControlPresets.getKey(toggleKeyLiteral)
|
||||||
private val toggleKey: Int?; get() = toggleKeyLiteral // to support in-screen keybind changing
|
val toggleKey: Int?; get() = ControlPresets.getKey(toggleKeyLiteral).let { if (it == -1) null else it } // to support in-screen keybind changing
|
||||||
private val toggleButton: Int?; get() = toggleButtonLiteral // to support in-screen keybind changing
|
// ControlPresets.getKey(toggleButtonLiteral)
|
||||||
|
val toggleButton: Int?; get() = ControlPresets.getKey(toggleButtonLiteral).let { if (it == -1) null else it } // to support in-screen keybind changing
|
||||||
|
|
||||||
|
|
||||||
val toggleKeyExtra: ArrayList<() -> Int> = arrayListOf()
|
val toggleKeyExtra: ArrayList<String> = arrayListOf()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a function that works with UIHandler.
|
* Takes a function that works with UIHandler.
|
||||||
@@ -207,14 +209,14 @@ void main() {
|
|||||||
else uiTogglerFunctionDefault!!.invoke(this)
|
else uiTogglerFunctionDefault!!.invoke(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleKeyExtra.forEachIndexed { index, getKey ->
|
toggleKeyExtra.forEachIndexed { index, control ->
|
||||||
if (Gdx.input.isKeyJustPressed(getKey())) {
|
if (Gdx.input.isKeyJustPressed(ControlPresets.getKey(control))) {
|
||||||
toggleKeyExtraAction[index].invoke(this)
|
toggleKeyExtraAction[index].invoke(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ESC is a master key for closing
|
// ESC is a master key for closing
|
||||||
if (allowESCtoClose && Gdx.input.isKeyJustPressed(Input.Keys.ESCAPE) && isOpened) {
|
if (!alwaysVisible && allowESCtoClose && Gdx.input.isKeyJustPressed(Input.Keys.ESCAPE) && isOpened) {
|
||||||
setAsClose()
|
setAsClose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,15 +17,15 @@ import kotlin.math.roundToInt
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class UIItemSpinner(
|
class UIItemSpinner(
|
||||||
parentUI: UICanvas,
|
parentUI: UICanvas,
|
||||||
initialX: Int, initialY: Int,
|
initialX: Int, initialY: Int,
|
||||||
private var initialValue: Number,
|
private var initialValue: Number,
|
||||||
val min: Number,
|
val min: Number,
|
||||||
val max: Number,
|
val max: Number,
|
||||||
val step: Number,
|
val step: Number,
|
||||||
override val width: Int,
|
override val width: Int,
|
||||||
private val drawBorder: Boolean = true,
|
private val drawBorder: Boolean = true,
|
||||||
private val numberToTextFunction: (Number) -> String = { "$it" }
|
private val numberToTextFunction: (Number) -> String = { "$it" }
|
||||||
) : UIItem(parentUI, initialX, initialY) {
|
) : UIItem(parentUI, initialX, initialY) {
|
||||||
|
|
||||||
// to alleviate floating point errors adding up as the spinner is being used
|
// to alleviate floating point errors adding up as the spinner is being used
|
||||||
|
|||||||
@@ -443,7 +443,7 @@ class UIItemTextLineInput(
|
|||||||
|
|
||||||
if (!mouseDown) mouseLatched = false
|
if (!mouseDown) mouseLatched = false
|
||||||
|
|
||||||
imeOn = KeyToggler.isOn(App.getConfigInt("control_key_toggleime"))
|
imeOn = KeyToggler.isOn(ControlPresets.getKey("control_key_toggleime"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,7 +468,7 @@ class UIItemTextLineInput(
|
|||||||
endComposing()
|
endComposing()
|
||||||
|
|
||||||
imeOn = !imeOn
|
imeOn = !imeOn
|
||||||
KeyToggler.forceSet(App.getConfigInt("control_key_toggleime"), imeOn)
|
KeyToggler.forceSet(ControlPresets.getKey("control_key_toggleime"), imeOn)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetIME() {
|
private fun resetIME() {
|
||||||
|
|||||||
@@ -17,13 +17,14 @@ import net.torvald.terrarum.gameworld.fmod
|
|||||||
* Created by minjaesong on 2021-10-21.
|
* Created by minjaesong on 2021-10-21.
|
||||||
*/
|
*/
|
||||||
class UIItemTextSelector(
|
class UIItemTextSelector(
|
||||||
parentUI: UICanvas,
|
parentUI: UICanvas,
|
||||||
initialX: Int, initialY: Int,
|
initialX: Int, initialY: Int,
|
||||||
val labelfuns: List<() -> String>,
|
val labelfuns: List<() -> String>,
|
||||||
initialSelection: Int,
|
initialSelection: Int,
|
||||||
override val width: Int,
|
override val width: Int,
|
||||||
private val drawBorder: Boolean = true,
|
private val drawBorder: Boolean = true,
|
||||||
private val clickToShowPalette: Boolean = true
|
private val clickToShowPalette: Boolean = true,
|
||||||
|
private val useSpinnerButtons: Boolean = false,
|
||||||
) : UIItem(parentUI, initialX, initialY) {
|
) : UIItem(parentUI, initialX, initialY) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -127,6 +128,9 @@ class UIItemTextSelector(
|
|||||||
else if (!Terrarum.mouseDown) mouseLatched = false
|
else if (!Terrarum.mouseDown) mouseLatched = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val leftIcon = if (useSpinnerButtons) labels.get(9,2) else labels.get(16,0)
|
||||||
|
private val rightIcon = if (useSpinnerButtons) labels.get(10,2) else labels.get(17,0)
|
||||||
|
|
||||||
override fun render(batch: SpriteBatch, camera: Camera) {
|
override fun render(batch: SpriteBatch, camera: Camera) {
|
||||||
labelCache = labelfuns.map { it() }
|
labelCache = labelfuns.map { it() }
|
||||||
|
|
||||||
@@ -184,12 +188,12 @@ class UIItemTextSelector(
|
|||||||
// left button icon
|
// left button icon
|
||||||
batch.color = if (mouseOnButton == 1 && mousePushed) Toolkit.Theme.COL_SELECTED
|
batch.color = if (mouseOnButton == 1 && mousePushed) Toolkit.Theme.COL_SELECTED
|
||||||
else if (mouseOnButton == 1) Toolkit.Theme.COL_MOUSE_UP else UIItemTextLineInput.TEXTINPUT_COL_TEXT
|
else if (mouseOnButton == 1) Toolkit.Theme.COL_MOUSE_UP else UIItemTextLineInput.TEXTINPUT_COL_TEXT
|
||||||
batch.draw(labels.get(16,0), posX + (buttonW - labels.tileW) / 2f, posY + (height - labels.tileH) / 2f)
|
batch.draw(leftIcon, posX + (buttonW - labels.tileW) / 2f, posY + (height - labels.tileH) / 2f)
|
||||||
|
|
||||||
// right button icon
|
// right button icon
|
||||||
batch.color = if (mouseOnButton == 2 && mousePushed) Toolkit.Theme.COL_SELECTED
|
batch.color = if (mouseOnButton == 2 && mousePushed) Toolkit.Theme.COL_SELECTED
|
||||||
else if (mouseOnButton == 2) Toolkit.Theme.COL_MOUSE_UP else UIItemTextLineInput.TEXTINPUT_COL_TEXT
|
else if (mouseOnButton == 2) Toolkit.Theme.COL_MOUSE_UP else UIItemTextLineInput.TEXTINPUT_COL_TEXT
|
||||||
batch.draw(labels.get(17,0), posX + width - buttonW + (buttonW - labels.tileW) / 2f, posY + (height - labels.tileH) / 2f)
|
batch.draw(rightIcon, posX + width - buttonW + (buttonW - labels.tileW) / 2f, posY + (height - labels.tileH) / 2f)
|
||||||
|
|
||||||
// draw text
|
// draw text
|
||||||
if (!paletteShowing) {
|
if (!paletteShowing) {
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
package net.torvald.terrarum.weather
|
package net.torvald.terrarum.weather
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
import com.badlogic.gdx.math.Vector3
|
||||||
|
import com.badlogic.gdx.utils.JsonValue
|
||||||
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.GdxColorMap
|
import net.torvald.terrarum.GdxColorMap
|
||||||
import java.util.*
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: Colour maps are likely to have sparse data points
|
* Note: Colour maps are likely to have sparse data points
|
||||||
@@ -12,10 +17,49 @@ import java.util.*
|
|||||||
* Created by minjaesong on 2016-07-11.
|
* Created by minjaesong on 2016-07-11.
|
||||||
*/
|
*/
|
||||||
data class BaseModularWeather(
|
data class BaseModularWeather(
|
||||||
var skyboxGradColourMap: GdxColorMap, // row 0: skybox grad top, row 1: skybox grad bottom, row 2: sunlight (RGBA)
|
val json: JsonValue,
|
||||||
val daylightClut: GdxColorMap,
|
var skyboxGradColourMap: GdxColorMap, // row 0: skybox grad top, row 1: skybox grad bottom, row 2: sunlight (RGBA)
|
||||||
val classification: String,
|
val daylightClut: GdxColorMap,
|
||||||
var extraImages: ArrayList<Texture>,
|
val classification: String,
|
||||||
val mixFrom: String? = null,
|
val cloudChance: Float,
|
||||||
val mixPercentage: Double? = null
|
val windSpeed: Float,
|
||||||
)
|
val windSpeedVariance: Float,
|
||||||
|
val cloudGamma: Vector2,
|
||||||
|
val cloudGammaVariance: Vector2,
|
||||||
|
var clouds: List<CloudProps>, // sorted by CloudProps.probability
|
||||||
|
|
||||||
|
val mixFrom: String? = null,
|
||||||
|
val mixPercentage: Double? = null,
|
||||||
|
|
||||||
|
var forceWindVec: Vector3? = null
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* @param rnd random number between -1 and +1
|
||||||
|
*/
|
||||||
|
fun getRandomWindSpeed(rnd: Float): Float {
|
||||||
|
val v = 1f + rnd.absoluteValue * windSpeedVariance
|
||||||
|
return if (rnd < 0) windSpeed / v else windSpeed * v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class CloudProps(
|
||||||
|
val category: String,
|
||||||
|
val spriteSheet: TextureRegionPack,
|
||||||
|
val probability: Float,
|
||||||
|
val baseScale: Float,
|
||||||
|
val scaleVariance: Float,
|
||||||
|
val altLow: Float,
|
||||||
|
val altHigh: Float,
|
||||||
|
) {
|
||||||
|
init {
|
||||||
|
spriteSheet.texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param rnd random number between -1 and +1
|
||||||
|
*/
|
||||||
|
fun getCloudScaleVariance(rnd: Float): Float {
|
||||||
|
val v = 1f + rnd.absoluteValue * scaleVariance
|
||||||
|
return if (rnd < 0) baseScale / v else baseScale * v
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,11 @@ package net.torvald.terrarum.weather
|
|||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.graphics.*
|
import com.badlogic.gdx.graphics.*
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
import com.badlogic.gdx.math.Vector3
|
||||||
|
import com.badlogic.gdx.utils.JsonValue
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.gdx.graphics.Cvec
|
import net.torvald.gdx.graphics.Cvec
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
@@ -16,9 +20,18 @@ import net.torvald.terrarum.gameworld.WorldTime.Companion.DAY_LENGTH
|
|||||||
import net.torvald.terrarum.RNGConsumer
|
import net.torvald.terrarum.RNGConsumer
|
||||||
import net.torvald.terrarum.clut.Skybox
|
import net.torvald.terrarum.clut.Skybox
|
||||||
import net.torvald.terrarum.utils.JsonFetcher
|
import net.torvald.terrarum.utils.JsonFetcher
|
||||||
|
import net.torvald.terrarum.utils.forEachSiblings
|
||||||
|
import net.torvald.terrarum.weather.WeatherObjectCloud.Companion.ALPHA_ROLLOFF_Z
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
import net.torvald.util.SortedArrayList
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileFilter
|
import java.io.FileFilter
|
||||||
|
import java.lang.Double.doubleToLongBits
|
||||||
|
import java.lang.Math.toDegrees
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
import kotlin.math.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently there is a debate whether this module must be part of the engine or the basegame
|
* Currently there is a debate whether this module must be part of the engine or the basegame
|
||||||
@@ -50,10 +63,11 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
lateinit var mixedWeather: BaseModularWeather
|
lateinit var mixedWeather: BaseModularWeather
|
||||||
|
|
||||||
val globalLightNow = Cvec(0)
|
val globalLightNow = Cvec(0)
|
||||||
|
private val moonlightMax = Cvec(0.23f, 0.24f, 0.25f, 0.21f) // actual moonlight is around ~4100K but our mesopic vision makes it appear blueish (wikipedia: Purkinje effect)
|
||||||
|
|
||||||
// Weather indices
|
// Weather indices
|
||||||
const val WEATHER_GENERIC = "generic"
|
const val WEATHER_GENERIC = "generic"
|
||||||
const val WEATHER_GENERIC_RAIN = "genericrain"
|
const val WEATHER_OVERCAST = "overcast"
|
||||||
// TODO add weather classification indices manually
|
// TODO add weather classification indices manually
|
||||||
|
|
||||||
// TODO to save from GL overhead, store lightmap to array; use GdxColorMap
|
// TODO to save from GL overhead, store lightmap to array; use GdxColorMap
|
||||||
@@ -68,16 +82,23 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
it.texture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat)
|
it.texture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val shaderBlendMax = App.loadShaderFromClasspath("shaders/blendSkyboxStars.vert", "shaders/blendSkyboxStars.frag")
|
private val shaderAstrum = App.loadShaderFromClasspath("shaders/blendSkyboxStars.vert", "shaders/blendSkyboxStars.frag")
|
||||||
|
private val shaderClouds = App.loadShaderFromClasspath("shaders/default.vert", "shaders/clouds.frag")
|
||||||
|
|
||||||
private var astrumOffX = 0f
|
private var astrumOffX = 0f
|
||||||
private var astrumOffY = 0f
|
private var astrumOffY = 0f
|
||||||
|
|
||||||
private val moonlightMax = Cvec(0.23f, 0.24f, 0.25f, 0.21f) // actual moonlight is around ~4100K but our mesopic vision makes it appear blueish (wikipedia: Purkinje effect)
|
private val clouds = SortedArrayList<WeatherObjectCloud>()
|
||||||
|
var cloudsSpawned = 0; private set
|
||||||
|
private var windVector = Vector3(-1f, 0f, 0.1f) // this is a direction vector
|
||||||
|
val cloudSpawnMax: Int
|
||||||
|
get() = 256 shl (App.getConfigInt("maxparticles") / 256)
|
||||||
|
|
||||||
override fun loadFromSave(s0: Long, s1: Long) {
|
override fun loadFromSave(s0: Long, s1: Long) {
|
||||||
super.loadFromSave(s0, s1)
|
super.loadFromSave(s0, s1)
|
||||||
|
currentWeather = weatherList[WEATHER_GENERIC]!![0]
|
||||||
internalReset(s0, s1)
|
internalReset(s0, s1)
|
||||||
|
initClouds()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun internalReset() = internalReset(RNG.state0, RNG.state1)
|
fun internalReset() = internalReset(RNG.state0, RNG.state1)
|
||||||
@@ -90,6 +111,15 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
astrumOffX = s0.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionWidth
|
astrumOffX = s0.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionWidth
|
||||||
astrumOffY = s1.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionHeight
|
astrumOffY = s1.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionHeight
|
||||||
|
|
||||||
|
clouds.clear()
|
||||||
|
cloudsSpawned = 0
|
||||||
|
windVector = Vector3(-0.98f, 0f, 0.21f)
|
||||||
|
|
||||||
|
windDirWindow = null
|
||||||
|
windSpeedWindow = null
|
||||||
|
|
||||||
|
oldCamPos.set(WorldCamera.camVector)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -121,6 +151,7 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
// initialise
|
// initialise
|
||||||
try {
|
try {
|
||||||
|
weatherList["titlescreen"] = arrayListOf(weatherList[WEATHER_GENERIC]!![0].copy(windSpeed = 1f))
|
||||||
currentWeather = weatherList[WEATHER_GENERIC]!![0]
|
currentWeather = weatherList[WEATHER_GENERIC]!![0]
|
||||||
nextWeather = getRandomWeather(WEATHER_GENERIC)
|
nextWeather = getRandomWeather(WEATHER_GENERIC)
|
||||||
}
|
}
|
||||||
@@ -128,10 +159,16 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|
||||||
val defaultWeather = BaseModularWeather(
|
val defaultWeather = BaseModularWeather(
|
||||||
|
JsonValue(JsonValue.ValueType.`object`),
|
||||||
GdxColorMap(1, 3, Color(0x55aaffff), Color(0xaaffffff.toInt()), Color.WHITE),
|
GdxColorMap(1, 3, Color(0x55aaffff), Color(0xaaffffff.toInt()), Color.WHITE),
|
||||||
GdxColorMap(2, 2, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE),
|
GdxColorMap(2, 2, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE),
|
||||||
"default",
|
"default",
|
||||||
ArrayList<Texture>()
|
0f,
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
Vector2(1f, 1f),
|
||||||
|
Vector2(0f, 0f),
|
||||||
|
listOf()
|
||||||
)
|
)
|
||||||
|
|
||||||
currentWeather = defaultWeather
|
currentWeather = defaultWeather
|
||||||
@@ -147,6 +184,9 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
// currentWeather = weatherList[WEATHER_GENERIC]!![0] // force set weather
|
// currentWeather = weatherList[WEATHER_GENERIC]!![0] // force set weather
|
||||||
|
|
||||||
|
updateWind(delta, world)
|
||||||
|
updateClouds(delta, world)
|
||||||
|
|
||||||
|
|
||||||
if (!globalLightOverridden) {
|
if (!globalLightOverridden) {
|
||||||
world.globalLight = WeatherMixer.globalLightNow
|
world.globalLight = WeatherMixer.globalLightNow
|
||||||
@@ -154,8 +194,330 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var turbidity = 4.0; private set
|
private fun FloatArray.shiftAndPut(f: Float) {
|
||||||
private var gH = 1.4f * App.scr.height
|
for (k in 1 until this.size) {
|
||||||
|
this[k-1] = this[k]
|
||||||
|
}
|
||||||
|
this[this.lastIndex] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
private val PI = 3.1415927f
|
||||||
|
private val TWO_PI = 6.2831855f
|
||||||
|
private val THREE_PI = 9.424778f
|
||||||
|
|
||||||
|
private var windDirWindow: FloatArray? = null
|
||||||
|
private var windSpeedWindow: FloatArray? = null
|
||||||
|
private val WIND_DIR_TIME_UNIT = 14400 // every 4hr
|
||||||
|
private val WIND_SPEED_TIME_UNIT = 3600 // every 1hr
|
||||||
|
private var windDirAkku = 0 // only needed if timeDelta is not divisible by WIND_TIME_UNIT
|
||||||
|
private var windSpeedAkku = 0
|
||||||
|
|
||||||
|
// see: https://stackoverflow.com/questions/2708476/rotation-interpolation/14498790#14498790
|
||||||
|
private fun getShortestAngle(start: Float, end: Float) =
|
||||||
|
(((((end - if (start < 0f) TWO_PI + start else start) % TWO_PI) + THREE_PI) % TWO_PI) - PI).let {
|
||||||
|
if (it > PI) it - TWO_PI else it
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateWind(delta: Float, world: GameWorld) {
|
||||||
|
if (windDirWindow == null) {
|
||||||
|
windDirWindow = FloatArray(4) { takeUniformRand(-PI..PI) } // completely random regardless of the seed
|
||||||
|
}
|
||||||
|
if (windSpeedWindow == null) {
|
||||||
|
windSpeedWindow = FloatArray(4) { currentWeather.getRandomWindSpeed(takeTriangularRand(-1f..1f)) } // completely random regardless of the seed
|
||||||
|
}
|
||||||
|
|
||||||
|
val windDirStep = windDirAkku / WIND_DIR_TIME_UNIT.toFloat()
|
||||||
|
val windSpeedStep = windSpeedAkku / WIND_SPEED_TIME_UNIT.toFloat()
|
||||||
|
|
||||||
|
// val angle0 = windDirWindow[0]
|
||||||
|
// val angle1 = getShortestAngle(angle0, windDirWindow[1])
|
||||||
|
// val angle2 = getShortestAngle(angle1, windDirWindow[2])
|
||||||
|
// val angle3 = getShortestAngle(angle2, windDirWindow[3])
|
||||||
|
// val fixedAngles = floatArrayOf(angle0, angle1, angle2, angle3)
|
||||||
|
|
||||||
|
val currentWindDir = FastMath.interpolateCatmullRom(windDirStep, windDirWindow)
|
||||||
|
val currentWindSpeed = FastMath.interpolateCatmullRom(windSpeedStep, windSpeedWindow)
|
||||||
|
/*
|
||||||
|
printdbg(this,
|
||||||
|
"dir ${Math.toDegrees(currentWindDir.toDouble()).roundToInt()}\t" +
|
||||||
|
"spd ${currentWindSpeed.times(10f).roundToInt().div(10f)}\t " +
|
||||||
|
"dirs ${windDirWindow!!.map { Math.toDegrees(it.toDouble()).roundToInt() }} ${windDirStep.times(100).roundToInt()}\t" +
|
||||||
|
"spds ${windSpeedWindow!!.map { it.times(10f).roundToInt().div(10f) }} ${windSpeedStep.times(100).roundToInt()}"
|
||||||
|
)*/
|
||||||
|
|
||||||
|
if (currentWeather.forceWindVec != null) {
|
||||||
|
windVector.set(currentWeather.forceWindVec)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
windVector.set(
|
||||||
|
cos(currentWindDir) * currentWindSpeed,
|
||||||
|
0f,
|
||||||
|
sin(currentWindDir) * currentWindSpeed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
while (windDirAkku >= WIND_DIR_TIME_UNIT) {
|
||||||
|
windDirAkku -= WIND_DIR_TIME_UNIT
|
||||||
|
windDirWindow!!.shiftAndPut(takeUniformRand(-PI..PI))
|
||||||
|
}
|
||||||
|
while (windSpeedAkku >= WIND_SPEED_TIME_UNIT) {
|
||||||
|
windSpeedAkku -= WIND_SPEED_TIME_UNIT
|
||||||
|
windSpeedWindow!!.shiftAndPut(currentWeather.getRandomWindSpeed(takeTriangularRand(-1f..1f)))
|
||||||
|
}
|
||||||
|
|
||||||
|
windDirAkku += world.worldTime.timeDelta
|
||||||
|
windSpeedAkku += world.worldTime.timeDelta
|
||||||
|
}
|
||||||
|
|
||||||
|
private val cloudParallaxMultY = -0.035f
|
||||||
|
private val cloudParallaxMultX = -0.035f
|
||||||
|
private var cloudUpdateAkku = 0f
|
||||||
|
private val oldCamPos = Vector2(0f, 0f)
|
||||||
|
private val camDelta = Vector2(0f, 0f)
|
||||||
|
|
||||||
|
val oobMarginR = 1.5f * App.scr.wf
|
||||||
|
val oobMarginL = -0.5f * App.scr.wf
|
||||||
|
private val oobMarginY = -0.5f * App.scr.hf
|
||||||
|
|
||||||
|
private val DEBUG_CAUSE_OF_DESPAWN = false
|
||||||
|
|
||||||
|
private fun updateClouds(delta: Float, world: GameWorld) {
|
||||||
|
val camvec = WorldCamera.camVector
|
||||||
|
val camvec2 = camvec.cpy()
|
||||||
|
val testCamDelta = camvec.cpy().sub(oldCamPos)
|
||||||
|
|
||||||
|
if (testCamDelta.x.absoluteValue > world.width * TILE_SIZEF / 2f) {
|
||||||
|
if (testCamDelta.x >= 0)
|
||||||
|
camvec2.x -= world.width * TILE_SIZEF
|
||||||
|
else
|
||||||
|
camvec2.x += world.width * TILE_SIZEF
|
||||||
|
|
||||||
|
testCamDelta.set(camvec2.sub(oldCamPos))
|
||||||
|
}
|
||||||
|
|
||||||
|
camDelta.set(testCamDelta)
|
||||||
|
|
||||||
|
|
||||||
|
val cloudChanceEveryMin = 60f / (currentWeather.cloudChance * currentWeather.windSpeed) // if chance = 0, the result will be +inf
|
||||||
|
|
||||||
|
while (cloudUpdateAkku >= cloudChanceEveryMin) {
|
||||||
|
cloudUpdateAkku -= cloudChanceEveryMin
|
||||||
|
tryToSpawnCloud(currentWeather)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var immDespawnCount = 0
|
||||||
|
val immDespawnCauses = ArrayList<String>()
|
||||||
|
clouds.forEach {
|
||||||
|
// do parallax scrolling
|
||||||
|
it.posX += camDelta.x * cloudParallaxMultX
|
||||||
|
it.posY += camDelta.y * cloudParallaxMultY
|
||||||
|
|
||||||
|
|
||||||
|
it.update(windVector)
|
||||||
|
|
||||||
|
if (DEBUG_CAUSE_OF_DESPAWN && it.life == 0) {
|
||||||
|
immDespawnCount += 1
|
||||||
|
immDespawnCauses.add(it.despawnCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// printdbg(this, "Newborn cloud death rate: $immDespawnCount/$cloudsSpawned")
|
||||||
|
|
||||||
|
|
||||||
|
if (DEBUG_CAUSE_OF_DESPAWN && App.IS_DEVELOPMENT_BUILD && immDespawnCount > cloudsSpawned / 4) {
|
||||||
|
val despawnCauseStats = HashMap<String, Int>()
|
||||||
|
immDespawnCauses.forEach {
|
||||||
|
if (despawnCauseStats[it] != null) {
|
||||||
|
despawnCauseStats[it] = despawnCauseStats[it]!! + 1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
despawnCauseStats[it] = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
despawnCauseStats.forEach { s, i ->
|
||||||
|
printdbg(this, "Cause of death -- $s: $i")
|
||||||
|
}
|
||||||
|
System.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// remove clouds that are marked to be despawn
|
||||||
|
var i = 0
|
||||||
|
while (true) {
|
||||||
|
if (i >= clouds.size) break
|
||||||
|
|
||||||
|
if (clouds[i].flagToDespawn) {
|
||||||
|
clouds.removeAt(i)
|
||||||
|
i -= 1
|
||||||
|
cloudsSpawned -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cloudUpdateAkku += delta
|
||||||
|
|
||||||
|
|
||||||
|
oldCamPos.set(camvec)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val scrHscaler = App.scr.height / 720f
|
||||||
|
private val cloudSizeMult = App.scr.wf / TerrarumScreenSize.defaultW
|
||||||
|
|
||||||
|
private fun takeUniformRand(range: ClosedFloatingPointRange<Float>) =
|
||||||
|
FastMath.interpolateLinear(Math.random().toFloat(), range.start, range.endInclusive)
|
||||||
|
private fun takeTriangularRand(range: ClosedFloatingPointRange<Float>) =
|
||||||
|
FastMath.interpolateLinear((Math.random() + Math.random()).div(2f).toFloat(), range.start, range.endInclusive)
|
||||||
|
private fun takeGaussianRand(range: ClosedFloatingPointRange<Float>) =
|
||||||
|
FastMath.interpolateLinear((Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random()).div(8f).toFloat(), range.start, range.endInclusive)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns random point for clouds to spawn from, in the opposite side of the current wind vector
|
||||||
|
*/
|
||||||
|
private fun getCloudSpawningPosition(cloud: CloudProps, halfCloudSize: Float, windVector: Vector3): Vector3 {
|
||||||
|
val Z_LIM = ALPHA_ROLLOFF_Z/2f
|
||||||
|
val y = takeUniformRand(-cloud.altHigh..-cloud.altLow) * scrHscaler
|
||||||
|
|
||||||
|
var windVectorDir = toDegrees(atan2(windVector.z.toDouble(), windVector.x.toDouble())).toFloat() + 180f
|
||||||
|
if (windVectorDir < 0f) windVectorDir += 360f
|
||||||
|
windVectorDir /= 90f // full circle: 4
|
||||||
|
|
||||||
|
// an "edge" is a line of length 1 drawn into the edge of the square of size 1 (its total edge length will be 4)
|
||||||
|
// when the windVectorDir is not an integer, the "edge" will take the shape similar to this: ¬
|
||||||
|
// 'rr' is a point on the "edge", where 0.5 is a middle point in its length
|
||||||
|
// val rl = (windVectorDir % 1f).let { if (it < 0.5f) -it else it - 1f }.toInt()
|
||||||
|
// val rh = 1 + (windVectorDir % 1f).let { if (it < 0.5f) it else 1f - it }.toInt()
|
||||||
|
|
||||||
|
// choose between rl and rh using (windVectorDir % 1f) as a pivot
|
||||||
|
// if pivot = 0.3, rL is 70%, and rR is 30% likely
|
||||||
|
// plug the vote result into the when()
|
||||||
|
val selectedQuadrant = takeUniformRand(windVectorDir..windVectorDir + 1f)
|
||||||
|
|
||||||
|
// printdbg(this, "Dir: $windVectorDir, Rand(${windVectorDir}..${windVectorDir + 1f}) = ${selectedQuadrant.floorToInt()}($selectedQuadrant)")
|
||||||
|
|
||||||
|
val rr = takeUniformRand(0f..1f)
|
||||||
|
|
||||||
|
return when (selectedQuadrant.floorToInt()) {
|
||||||
|
-4, 0, 4 -> { // right side of the screen
|
||||||
|
val z = FastMath.interpolateLinear(rr, 1f, ALPHA_ROLLOFF_Z).pow(1.5f) // clouds are more likely to spawn with low Z-value
|
||||||
|
val posXscr = App.scr.width + halfCloudSize
|
||||||
|
val x = WeatherObjectCloud.screenXtoWorldX(posXscr, z)
|
||||||
|
Vector3(x, y, z)
|
||||||
|
}
|
||||||
|
-3, 1, 5 -> { // z = inf
|
||||||
|
val z = ALPHA_ROLLOFF_Z
|
||||||
|
val posXscr = FastMath.interpolateLinear(rr, App.scr.width + halfCloudSize, -halfCloudSize)
|
||||||
|
val x = WeatherObjectCloud.screenXtoWorldX(posXscr, Z_LIM)
|
||||||
|
Vector3(x, y, z)
|
||||||
|
}
|
||||||
|
-2, 2, 6 -> { // left side of the screen
|
||||||
|
val z = FastMath.interpolateLinear(rr, ALPHA_ROLLOFF_Z, 1f).pow(1.5f) // clouds are more likely to spawn with low Z-value
|
||||||
|
val posXscr = -halfCloudSize
|
||||||
|
val x = WeatherObjectCloud.screenXtoWorldX(posXscr, z)
|
||||||
|
Vector3(x, y, z)
|
||||||
|
}
|
||||||
|
-1, 3, 7 -> { // z = 0
|
||||||
|
val z = 0.1f
|
||||||
|
val posXscr = FastMath.interpolateLinear(rr, -halfCloudSize, App.scr.width + halfCloudSize)
|
||||||
|
val x = WeatherObjectCloud.screenXtoWorldX(posXscr, Z_LIM)
|
||||||
|
Vector3(x, y, z)
|
||||||
|
}
|
||||||
|
else -> throw InternalError()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun tryToSpawnCloud(currentWeather: BaseModularWeather, precalculatedPos: Vector3? = null) {
|
||||||
|
// printdbg(this, "Trying to spawn a cloud... (${cloudsSpawned} / ${cloudSpawnMax})")
|
||||||
|
|
||||||
|
if (cloudsSpawned < cloudSpawnMax) {
|
||||||
|
val flip = Math.random() < 0.5
|
||||||
|
val rC = takeUniformRand(0f..1f)
|
||||||
|
// val rZ = takeUniformRand(1f..ALPHA_ROLLOFF_Z/4f).pow(1.5f) // clouds are more likely to spawn with low Z-value
|
||||||
|
// val rY = takeUniformRand(-1f..1f)
|
||||||
|
val rT1 = takeTriangularRand(-1f..1f)
|
||||||
|
val (rA, rB) = doubleToLongBits(Math.random()).let {
|
||||||
|
it.ushr(20).and(0xFFFF).toInt() to it.ushr(36).and(0xFFFF).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
var cloudsToSpawn: CloudProps? = null
|
||||||
|
var c = 0
|
||||||
|
while (c < currentWeather.clouds.size) {
|
||||||
|
if (rC < currentWeather.clouds[c].probability) {
|
||||||
|
cloudsToSpawn = currentWeather.clouds[c]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cloudsToSpawn?.let { cloud ->
|
||||||
|
val cloudScale = cloud.getCloudScaleVariance(rT1)
|
||||||
|
val hCloudSize = (cloud.spriteSheet.tileW * cloudScale) / 2f + 1f
|
||||||
|
|
||||||
|
// val posXscr = initX ?: if (cloudDriftVector.x < 0) (App.scr.width + hCloudSize) else -hCloudSize
|
||||||
|
// val posX = WeatherObjectCloud.screenXtoWorldX(posXscr, rZ)
|
||||||
|
// val posY = randomPosWithin(-cloud.altHigh..-cloud.altLow, rY) * scrHscaler
|
||||||
|
|
||||||
|
val sheetX = rA % cloud.spriteSheet.horizontalCount
|
||||||
|
val sheetY = rB % cloud.spriteSheet.verticalCount
|
||||||
|
WeatherObjectCloud(cloud.spriteSheet.get(sheetX, sheetY), flip).also {
|
||||||
|
it.scale = cloudScale * cloudSizeMult
|
||||||
|
|
||||||
|
it.pos.set(precalculatedPos ?: getCloudSpawningPosition(cloud, hCloudSize, windVector))
|
||||||
|
|
||||||
|
// further set the random altitude if required
|
||||||
|
if (precalculatedPos != null) {
|
||||||
|
it.pos.y = takeUniformRand(-cloud.altHigh..-cloud.altLow) * scrHscaler
|
||||||
|
}
|
||||||
|
|
||||||
|
clouds.add(it)
|
||||||
|
cloudsSpawned += 1
|
||||||
|
|
||||||
|
|
||||||
|
// printdbg(this, "... Spawning ${cloud.category}($sheetX, $sheetY) cloud at pos ${it.pos}, scale ${it.scale}, invGamma ${it.darkness}")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initClouds() {
|
||||||
|
val hCloudSize = 1024f
|
||||||
|
// multiplier is an empirical value that depends on the 'rZ'
|
||||||
|
// it does converge at ~6, but having it as an initial state does not make it stay converged
|
||||||
|
repeat((currentWeather.cloudChance * 1.333f).ceilToInt()) {
|
||||||
|
|
||||||
|
val z = takeUniformRand(0.1f..ALPHA_ROLLOFF_Z / 4f - 0.1f).pow(1.5f) // clouds are more likely to spawn with low Z-value
|
||||||
|
|
||||||
|
val zz = FastMath.interpolateLinear((z / ALPHA_ROLLOFF_Z) * 0.8f + 0.1f, ALPHA_ROLLOFF_Z / 4f, ALPHA_ROLLOFF_Z)
|
||||||
|
|
||||||
|
val x = WeatherObjectCloud.screenXtoWorldX(takeUniformRand(0f..App.scr.wf), zz)
|
||||||
|
|
||||||
|
|
||||||
|
tryToSpawnCloud(currentWeather, Vector3(x, 0f, z))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun titleScreenInitWeather() {
|
||||||
|
currentWeather = weatherList["titlescreen"]!![0]
|
||||||
|
currentWeather.forceWindVec = Vector3(-0.98f, 0f, -0.21f)
|
||||||
|
initClouds()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> Array<T?>.addAtFreeSpot(obj: T) {
|
||||||
|
var c = 0
|
||||||
|
while (true) {
|
||||||
|
if (this[c] == null) break
|
||||||
|
c += 1
|
||||||
|
}
|
||||||
|
this[c] = obj
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var turbidity = 1.0; private set
|
||||||
|
private var gH = 1.8f * App.scr.height
|
||||||
// private var gH = 0.8f * App.scr.height
|
// private var gH = 0.8f * App.scr.height
|
||||||
|
|
||||||
internal var parallaxPos = 0f; private set
|
internal var parallaxPos = 0f; private set
|
||||||
@@ -166,11 +528,28 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
*/
|
*/
|
||||||
internal fun render(camera: Camera, batch: FlippingSpriteBatch, world: GameWorld) {
|
internal fun render(camera: Camera, batch: FlippingSpriteBatch, world: GameWorld) {
|
||||||
drawSkybox(camera, batch, world)
|
drawSkybox(camera, batch, world)
|
||||||
|
drawClouds(batch)
|
||||||
|
batch.color = Color.WHITE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun drawClouds(batch: SpriteBatch) {
|
||||||
|
batch.inUse { _ ->
|
||||||
|
batch.shader = shaderClouds
|
||||||
|
batch.shader.setUniformf("gamma", currentWeather.cloudGamma)
|
||||||
|
batch.shader.setUniformf("shadeCol", 0.06f, 0.07f, 0.08f, 1f) // TODO temporary value
|
||||||
|
|
||||||
|
clouds.forEach {
|
||||||
|
batch.color = Color(globalLightNow.r, globalLightNow.g, globalLightNow.b, it.alpha)
|
||||||
|
it.render(batch, 0f, 0f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val parallaxDomainSize = 400f
|
||||||
|
private val turbidityDomainSize = 533.3333f
|
||||||
|
|
||||||
private fun drawSkybox(camera: Camera, batch: FlippingSpriteBatch, world: GameWorld) {
|
private fun drawSkybox(camera: Camera, batch: FlippingSpriteBatch, world: GameWorld) {
|
||||||
val parallaxZeroPos = (world.height / 3f)
|
val parallaxZeroPos = (world.height / 3f)
|
||||||
val parallaxDomainSize = 300f
|
|
||||||
|
|
||||||
// we will not care for nextSkybox for now
|
// we will not care for nextSkybox for now
|
||||||
val timeNow = (forceTimeAt ?: world.worldTime.TIME_T.toInt()) % WorldTime.DAY_LENGTH
|
val timeNow = (forceTimeAt ?: world.worldTime.TIME_T.toInt()) % WorldTime.DAY_LENGTH
|
||||||
@@ -199,17 +578,20 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
-+ <- 0.0 =
|
-+ <- 0.0 =
|
||||||
*/
|
*/
|
||||||
val parallax = ((parallaxZeroPos - WorldCamera.gdxCamY.div(TILE_SIZEF)) / parallaxDomainSize).times(-1f).coerceIn(-1f, 1f)
|
val parallax = ((parallaxZeroPos - WorldCamera.gdxCamY.div(TILE_SIZEF)) / parallaxDomainSize).times(-1f).coerceIn(-1f, 1f)
|
||||||
|
val turbidityCoeff = ((parallaxZeroPos - WorldCamera.gdxCamY.div(TILE_SIZEF)) / turbidityDomainSize).times(-1f).coerceIn(-1f, 1f)
|
||||||
parallaxPos = parallax
|
parallaxPos = parallax
|
||||||
// println(parallax) // parallax value works as intended.
|
// println(parallax) // parallax value works as intended.
|
||||||
|
|
||||||
gdxBlendNormalStraightAlpha()
|
gdxBlendNormalStraightAlpha()
|
||||||
|
|
||||||
|
turbidity = (3.5 + turbidityCoeff * 2.5).coerceIn(1.0, 6.0)
|
||||||
val thisTurbidity = forceTurbidity ?: turbidity
|
val thisTurbidity = forceTurbidity ?: turbidity
|
||||||
|
|
||||||
// TODO trilinear with (deg, turb, alb)
|
|
||||||
val gradY = -(gH - App.scr.height) * ((parallax + 1f) / 2f)
|
val gradY = -(gH - App.scr.height) * ((parallax + 1f) / 2f)
|
||||||
val (tex, uvs) = Skybox.getUV(solarElev, thisTurbidity, 0.3)
|
|
||||||
|
|
||||||
|
val (tex, uvs, turbX, albX) = Skybox.getUV(solarElev, thisTurbidity, 0.3)
|
||||||
|
|
||||||
|
val mornNoonBlend = (1f/4000f * (timeNow - 43200) + 0.5f).coerceIn(0f, 1f) // 0.0 at T41200; 0.5 at T43200; 1.0 at T45200;
|
||||||
|
|
||||||
starmapTex.texture.bind(1)
|
starmapTex.texture.bind(1)
|
||||||
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
|
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
|
||||||
@@ -218,22 +600,28 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
val astrumY = ((world.worldTime.TIME_T / WorldTime.DIURNAL_MOTION_LENGTH) % 1f) * starmapTex.regionHeight
|
val astrumY = ((world.worldTime.TIME_T / WorldTime.DIURNAL_MOTION_LENGTH) % 1f) * starmapTex.regionHeight
|
||||||
|
|
||||||
batch.inUse {
|
batch.inUse {
|
||||||
batch.shader = shaderBlendMax
|
batch.shader = shaderAstrum
|
||||||
shaderBlendMax.setUniformi("tex1", 1)
|
shaderAstrum.setUniformi("tex1", 1)
|
||||||
shaderBlendMax.setUniformf("drawOffset", 0f, gradY)
|
shaderAstrum.setUniformf("drawOffsetSize", 0f, gradY, App.scr.wf, gH)
|
||||||
shaderBlendMax.setUniformf("drawOffsetSize", App.scr.wf, gH)
|
shaderAstrum.setUniform4fv("uvA", uvs, 0, 4)
|
||||||
shaderBlendMax.setUniform2fv("skyboxUV1", uvs, 0, 2)
|
shaderAstrum.setUniform4fv("uvB", uvs, 4, 4)
|
||||||
shaderBlendMax.setUniform2fv("skyboxUV2", uvs, 2, 2)
|
shaderAstrum.setUniform4fv("uvC", uvs, 8, 4)
|
||||||
shaderBlendMax.setUniformf("astrumScroll", astrumOffX + astrumX, astrumOffY + astrumY)
|
shaderAstrum.setUniform4fv("uvD", uvs, 12, 4)
|
||||||
shaderBlendMax.setUniformf("randomNumber",
|
shaderAstrum.setUniform4fv("uvE", uvs, 16, 4)
|
||||||
|
shaderAstrum.setUniform4fv("uvF", uvs, 20, 4)
|
||||||
|
shaderAstrum.setUniform4fv("uvG", uvs, 24, 4)
|
||||||
|
shaderAstrum.setUniform4fv("uvH", uvs, 28, 4)
|
||||||
|
shaderAstrum.setUniformf("texBlend", mornNoonBlend, turbX, albX, 0f)
|
||||||
|
shaderAstrum.setUniformf("astrumScroll", astrumOffX + astrumX, astrumOffY + astrumY)
|
||||||
|
shaderAstrum.setUniformf("randomNumber",
|
||||||
// (world.worldTime.TIME_T.plus(31L) xor 1453L + 31L).and(1023).toFloat(),
|
// (world.worldTime.TIME_T.plus(31L) xor 1453L + 31L).and(1023).toFloat(),
|
||||||
// (world.worldTime.TIME_T.plus(37L) xor 862L + 31L).and(1023).toFloat(),
|
// (world.worldTime.TIME_T.plus(37L) xor 862L + 31L).and(1023).toFloat(),
|
||||||
// (world.worldTime.TIME_T.plus(23L) xor 1639L + 29L).and(1023).toFloat(),
|
// (world.worldTime.TIME_T.plus(23L) xor 1639L + 29L).and(1023).toFloat(),
|
||||||
// (world.worldTime.TIME_T.plus(29L) xor 2971L + 41L).and(1023).toFloat(),
|
// (world.worldTime.TIME_T.plus(29L) xor 2971L + 41L).and(1023).toFloat(),
|
||||||
world.worldTime.TIME_T.div(+12.1f).plus(31L),
|
world.worldTime.TIME_T.div(+14.1f).plus(31L),
|
||||||
world.worldTime.TIME_T.div(-11.8f).plus(37L),
|
world.worldTime.TIME_T.div(-13.8f).plus(37L),
|
||||||
world.worldTime.TIME_T.div(+11.9f).plus(23L),
|
world.worldTime.TIME_T.div(+13.9f).plus(23L),
|
||||||
world.worldTime.TIME_T.div(-12.3f).plus(29L),
|
world.worldTime.TIME_T.div(-14.3f).plus(29L),
|
||||||
)
|
)
|
||||||
|
|
||||||
batch.color = Color.WHITE
|
batch.color = Color.WHITE
|
||||||
@@ -355,20 +743,36 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
val skyboxInJson = JSON.getString("skyboxGradColourMap")
|
val skyboxInJson = JSON.getString("skyboxGradColourMap")
|
||||||
val lightbox = JSON.getString("daylightClut")
|
val lightbox = JSON.getString("daylightClut")
|
||||||
val extraImagesPath = JSON.get("extraImages").asStringArray()
|
|
||||||
|
|
||||||
val skybox = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${skyboxInJson}"))
|
val skybox = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${skyboxInJson}"))
|
||||||
val daylight = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${lightbox}"))
|
val daylight = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${lightbox}"))
|
||||||
|
|
||||||
|
|
||||||
val extraImages = ArrayList<Texture>()
|
|
||||||
for (i in extraImagesPath)
|
|
||||||
extraImages.add(Texture(ModMgr.getGdxFile(modname, "$pathToImage/${i}")))
|
|
||||||
|
|
||||||
|
|
||||||
val classification = JSON.getString("classification")
|
val classification = JSON.getString("classification")
|
||||||
|
|
||||||
|
|
||||||
|
val cloudsMap = ArrayList<CloudProps>()
|
||||||
|
val clouds = JSON["clouds"]
|
||||||
|
clouds.forEachSiblings { name, json ->
|
||||||
|
cloudsMap.add(CloudProps(
|
||||||
|
name,
|
||||||
|
TextureRegionPack(ModMgr.getGdxFile(modname, "$pathToImage/${json.getString("filename")}"), json.getInt("tw"), json.getInt("th")),
|
||||||
|
json.getFloat("probability"),
|
||||||
|
json.getFloat("baseScale"),
|
||||||
|
json.getFloat("scaleVariance"),
|
||||||
|
json.getFloat("altLow"),
|
||||||
|
json.getFloat("altHigh"),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
cloudsMap.sortBy { it.probability }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var mixFrom: String?
|
var mixFrom: String?
|
||||||
try { mixFrom = JSON.getString("mixFrom") }
|
try { mixFrom = JSON.getString("mixFrom") }
|
||||||
@@ -383,20 +787,28 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
|
|
||||||
return BaseModularWeather(
|
return BaseModularWeather(
|
||||||
|
json = JSON,
|
||||||
skyboxGradColourMap = skybox,
|
skyboxGradColourMap = skybox,
|
||||||
daylightClut = daylight,
|
daylightClut = daylight,
|
||||||
classification = classification,
|
classification = classification,
|
||||||
extraImages = extraImages
|
cloudChance = JSON.getFloat("cloudChance"),
|
||||||
|
windSpeed = JSON.getFloat("windSpeed"),
|
||||||
|
windSpeedVariance = JSON.getFloat("windSpeedVariance"),
|
||||||
|
cloudGamma = JSON["cloudGamma"].asFloatArray().let { Vector2(it[0], it[1]) },
|
||||||
|
cloudGammaVariance = JSON["cloudGammaVariance"].asFloatArray().let { Vector2(it[0], it[1]) },
|
||||||
|
clouds = cloudsMap,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dispose() {
|
fun dispose() {
|
||||||
weatherList.values.forEach { list ->
|
weatherList.values.forEach { list ->
|
||||||
list.forEach { weather ->
|
list.forEach { weather ->
|
||||||
weather.extraImages.forEach { it.tryDispose() }
|
weather.clouds.forEach { it.spriteSheet.dispose() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
starmapTex.texture.dispose()
|
starmapTex.texture.dispose()
|
||||||
shaderBlendMax.dispose()
|
shaderAstrum.dispose()
|
||||||
|
shaderClouds.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user