mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 16:44:05 +09:00
Compare commits
40 Commits
v0.3.2
...
v0.3.3-tes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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
|
||||
|
||||
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 kotlin.coroutines.*
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
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.FixtureBase
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarum.modulecomputers.ui.UIHomeComputer
|
||||
import net.torvald.tsvm.*
|
||||
import net.torvald.tsvm.peripheral.AdapterConfig
|
||||
import net.torvald.tsvm.peripheral.GraphicsAdapter
|
||||
import net.torvald.tsvm.peripheral.VMProgramRom
|
||||
import net.torvald.unicode.*
|
||||
|
||||
/**
|
||||
* 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,93 @@
|
||||
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.App
|
||||
import net.torvald.terrarum.FlippingSpriteBatch
|
||||
import net.torvald.terrarum.blendNormalStraightAlpha
|
||||
import net.torvald.terrarum.inAction
|
||||
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 = 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()
|
||||
}
|
||||
|
||||
}
|
||||
BIN
assets/clut/skybox.png
LFS
BIN
assets/clut/skybox.png
LFS
Binary file not shown.
@@ -23,6 +23,7 @@
|
||||
"MENU_LABEL_STREAMING": "Livestreaming",
|
||||
"MENU_LABEL_SYSTEM_INFO": "System Info",
|
||||
"MENU_MODULES" : "Modules",
|
||||
"MENU_OPTIONS_ATLAS_TEXTURE_SIZE": "Atlas Texture Size",
|
||||
"MENU_OPTIONS_AUTOSAVE": "Autosave",
|
||||
"MENU_OPTIONS_BLUR": "Blur",
|
||||
"MENU_OPTIONS_DEBUG_CONSOLE": "Debug Console",
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"MENU_LABEL_STREAMING": "실시간 방송",
|
||||
"MENU_LABEL_SYSTEM_INFO": "시스템 정보",
|
||||
"MENU_MODULES" : "모듈",
|
||||
"MENU_OPTIONS_ATLAS_TEXTURE_SIZE": "아틀라스 텍스처 크기",
|
||||
"MENU_OPTIONS_AUTOSAVE": "자동 저장",
|
||||
"MENU_OPTIONS_BLUR": "흐림",
|
||||
"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"
|
||||
"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"
|
||||
"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"
|
||||
@@ -188,6 +188,7 @@
|
||||
## 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.
|
||||
## - 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 ##
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 179 and column 37.
|
@@ -8,6 +8,7 @@ id;classname
|
||||
8;net.torvald.terrarum.modulebasegame.gameitems.ItemLogicSignalEmitter
|
||||
9;net.torvald.terrarum.modulebasegame.gameitems.WireCutterAll
|
||||
10;net.torvald.terrarum.modulebasegame.gameitems.ItemTypewriter
|
||||
11;net.torvald.terrarum.modulebasegame.gameitems.ItemWallCalendar
|
||||
|
||||
256;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorOak
|
||||
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",
|
||||
"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",
|
||||
"CONTEXT_GENERATOR_SEED": "Seed",
|
||||
"MENU_LABEL_PREV_SAVES": "Previous Saves",
|
||||
"MENU_LABEL_RENAME": "Rename",
|
||||
"GAME_ACTION_CRAFT": "Craft",
|
||||
"GAME_ACTION_GRAPPLE": "Grapple",
|
||||
"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",
|
||||
"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_FULL_COLLISION": "Urist Berdanrifot",
|
||||
"ACTORBLOCK_NO_COLLISION": "Urist Zafal",
|
||||
"ACTORBLOCK_NO_PASS_RIGHT": "Urist McPassLeft",
|
||||
"ACTORBLOCK_NO_PASS_LEFT": "Urist McPassRight",
|
||||
"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"
|
||||
"ACTORBLOCK_TILING_PLACEHOLDER": "Urist Berdanurdim"
|
||||
}
|
||||
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": "새 세계",
|
||||
"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": "메뉴",
|
||||
"CONTEXT_ITEM_MAP": "지도",
|
||||
"CONTEXT_GENERATOR_SEED": "시드",
|
||||
"MENU_LABEL_PREV_SAVES": "이전 세이브",
|
||||
"MENU_LABEL_RENAME": "이름 바꾸기",
|
||||
"MENU_MONITOR_CALI_TITLE": "모니터 확인",
|
||||
"GAME_ACTION_CRAFT": "제작하기",
|
||||
"GAME_ACTION_GRAPPLE": "매달리기",
|
||||
"GAME_ACTION_QUICKSEL": "빠른 선택",
|
||||
"GAME_ACTION_CRAFT": "제작하기",
|
||||
"GAME_CRAFTING": "제작",
|
||||
"GAME_CRAFTABLE_ITEMS": "제작 가능한 아이템",
|
||||
"MENU_LABEL_RENAME": "이름 바꾸기",
|
||||
"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_STONE_MARBLE": "대리석",
|
||||
|
||||
"ITEM_STORAGE_CHEST": "보관상자",
|
||||
"ITEM_WIRE": "전선",
|
||||
"ITEM_WIRE_CUTTER": "전선 절단기",
|
||||
"ITEM_CALENDAR": "달력",
|
||||
"ITEM_LOGIC_SIGNAL_EMITTER": "신호발생기",
|
||||
"ITEM_TIKI_TORCH": "티키 토치"
|
||||
"ITEM_STORAGE_CHEST": "보관상자",
|
||||
"ITEM_TIKI_TORCH": "티키 토치",
|
||||
"ITEM_TYPEWRITER": "타자기",
|
||||
"ITEM_WIRE": "전선",
|
||||
"ITEM_WIRE_CUTTER": "전선 절단기"
|
||||
}
|
||||
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.
@@ -3,7 +3,8 @@ if (( $EUID == 0 )); then echo "The build process is not meant to be run with ro
|
||||
|
||||
cd "${0%/*}"
|
||||
SRCFILES="terrarummac_arm"
|
||||
DESTDIR="out/TerrarumMac.arm.app"
|
||||
APPDIR="./TerrarumMac.arm.app"
|
||||
DESTDIR="out/$APPDIR"
|
||||
RUNTIME="runtime-osx-arm"
|
||||
|
||||
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
|
||||
cp "../out/TerrarumBuild.jar" $DESTDIR/Contents/MacOS/out/
|
||||
|
||||
cd "out"
|
||||
rm $APPDIR.zip
|
||||
7z a -tzip $APPDIR.zip $APPDIR
|
||||
|
||||
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%/*}"
|
||||
SRCFILES="terrarummac_x86"
|
||||
DESTDIR="out/TerrarumMac.x86.app"
|
||||
APPDIR="./TerrarumMac.x86.app"
|
||||
DESTDIR="out/$APPDIR"
|
||||
RUNTIME="runtime-osx-x86"
|
||||
|
||||
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
|
||||
cp "../out/TerrarumBuild.jar" $DESTDIR/Contents/MacOS/out/
|
||||
|
||||
cd "out"
|
||||
rm $APPDIR.zip
|
||||
7z a -tzip $APPDIR.zip $APPDIR
|
||||
|
||||
echo "Build successful: $DESTDIR"
|
||||
|
||||
25
buildapp/make_assets_release.sh
Executable file
25
buildapp/make_assets_release.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/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 -r $DESTDIR/mods/basegame/sounds
|
||||
rm -r $DESTDIR/mods/dwarventech
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -192,6 +192,16 @@ fun CIEXYZ.toColorRaw(): Color {
|
||||
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 {
|
||||
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.colourutil.*
|
||||
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.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.modulebasegame.worldgenerator.HALF_PI
|
||||
import net.torvald.terrarum.modulebasegame.worldgenerator.TWO_PI
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.FlowLayout
|
||||
import java.awt.GridLayout
|
||||
import java.lang.Math.pow
|
||||
import javax.swing.*
|
||||
import kotlin.math.*
|
||||
@@ -94,7 +92,16 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
||||
if (turbidity <= 0) throw IllegalStateException()
|
||||
|
||||
// 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)
|
||||
@@ -127,7 +134,7 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
||||
}
|
||||
|
||||
val outTexWidth = 1
|
||||
val outTexHeight = 256
|
||||
val outTexHeight = 128
|
||||
|
||||
private fun Float.scaleFun() =
|
||||
(1f - 1f / 2f.pow(this/6f)) * 0.97f
|
||||
@@ -142,14 +149,20 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
||||
)
|
||||
}
|
||||
else {
|
||||
val elevation1 = -Math.toDegrees(elevation)
|
||||
val elevation2 = -Math.toDegrees(elevation) / 28.5
|
||||
val scale = (1f - (1f - 1f / 1.8.pow(elevation1)) * 0.97f).toFloat()
|
||||
val scale2 = (1.0 - (elevation2.pow(E) / E.pow(elevation2))*0.8).toFloat()
|
||||
// maths model: https://www.desmos.com/calculator/cwi7iyzygg
|
||||
|
||||
val x = -Math.toDegrees(elevation).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(
|
||||
this.X.scaleFun() * scale * scale2,
|
||||
this.Y.scaleFun() * scale * scale2,
|
||||
this.Z.scaleFun() * scale * scale2,
|
||||
this.X.scaleFun() * f * h,
|
||||
this.Y.scaleFun() * f * h,
|
||||
this.Z.scaleFun() * f * h,
|
||||
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;
|
||||
* 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 {
|
||||
var v = y.coerceAtLeast(0.0)
|
||||
@@ -175,6 +188,7 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
||||
val ys2 = ArrayList<Float>()
|
||||
|
||||
val halfHeight = oneScreen.height * 0.5
|
||||
val elevationDeg = Math.toDegrees(elevation)
|
||||
|
||||
for (x in 0 until oneScreen.width) {
|
||||
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*/
|
||||
|
||||
// AM-PM mapping (use with WIDTH=1)
|
||||
var yf = (y * 2.0 / oneScreen.height) % 1.0
|
||||
if (elevation < 0) yf *= 1.0 - pow(-elevation / HALF_PI, 0.333)
|
||||
val yp = y % (oneScreen.height / 2)
|
||||
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 theta = yf.mapCircle() * HALF_PI
|
||||
|
||||
|
||||
|
||||
val xyz = CIEXYZ(
|
||||
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, 2).toFloat()
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 2).toFloat(),
|
||||
)
|
||||
val xyz2 = xyz.scaleToFit(elevation)
|
||||
ys.add(xyz.Y)
|
||||
@@ -204,12 +220,12 @@ class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
||||
val rgb = xyz2.toRGB().toColor()
|
||||
rgb.a = 1f
|
||||
|
||||
val rgb2 = Color(
|
||||
/*val rgb2 = Color(
|
||||
((rgb.r * 255f).roundToInt() xor 0xAA) / 255f,
|
||||
((rgb.g * 255f).roundToInt() xor 0xAA) / 255f,
|
||||
((rgb.b * 255f).roundToInt() xor 0xAA) / 255f,
|
||||
rgb.a
|
||||
)
|
||||
)*/
|
||||
|
||||
oneScreen.setColor(rgb)
|
||||
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 long VERSION_RAW = TerrarumAppConfiguration.VERSION_RAW;
|
||||
public static final String VERSION_TAG = TerrarumAppConfiguration.VERSION_TAG;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public static final float UPDATE_RATE = 1f / 64f; // apparent framerate will be limited by update rate
|
||||
public static final int TICKS = 64;
|
||||
public static final float UPDATE_RATE = 1f / TICKS; // apparent framerate will be limited by update rate
|
||||
|
||||
private static float loadTimer = 0f;
|
||||
private static final float showupTime = 100f / 1000f;
|
||||
|
||||
private static FloatFrameBuffer renderFBO;
|
||||
private static Float16FrameBuffer renderFBO;
|
||||
|
||||
public static HashSet<File> tempFilePool = new HashSet<>();
|
||||
|
||||
@@ -609,19 +612,21 @@ public class App implements ApplicationListener {
|
||||
|
||||
private static void processScreenshotRequest(FrameBuffer fb) {
|
||||
if (screenshotRequested) {
|
||||
String msg = "Screenshot taken";
|
||||
FrameBufferManager.begin(fb);
|
||||
try {
|
||||
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);
|
||||
p.dispose();
|
||||
Terrarum.INSTANCE.getIngame().sendNotification("Screenshot taken");
|
||||
}
|
||||
catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
Terrarum.INSTANCE.getIngame().sendNotification("Failed to take screenshot: "+e.getMessage());
|
||||
msg = ("Failed to take screenshot: "+e.getMessage());
|
||||
}
|
||||
FrameBufferManager.end();
|
||||
screenshotRequested = false;
|
||||
|
||||
Terrarum.INSTANCE.getIngame().sendNotification(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,12 +755,12 @@ public class App implements ApplicationListener {
|
||||
(renderFBO.getWidth() != scr.getWidth() ||
|
||||
renderFBO.getHeight() != scr.getHeight())
|
||||
) {
|
||||
renderFBO = new FloatFrameBuffer(
|
||||
renderFBO = new Float16FrameBuffer(
|
||||
scr.getWidth(),
|
||||
scr.getHeight(),
|
||||
false
|
||||
);
|
||||
postProcessorOutFBO2 = new FloatFrameBuffer(
|
||||
postProcessorOutFBO2 = new Float16FrameBuffer(
|
||||
scr.getWidth() * 2,
|
||||
scr.getHeight() * 2,
|
||||
false
|
||||
|
||||
@@ -62,9 +62,12 @@ basegame
|
||||
* 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.1: 2278
|
||||
// Commit counts up to the Release 0.3.2: 2732
|
||||
|
||||
const val VERSION_TAG: String = "test001"
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// CONFIGURATION FOR TILE MAKER //
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.badlogic.gdx.math.Matrix4
|
||||
import com.badlogic.gdx.utils.Disposable
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.App.IS_DEVELOPMENT_BUILD
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.ui.BasicDebugInfoWindow
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
@@ -150,9 +151,10 @@ object TerrarumPostProcessor : Disposable {
|
||||
}
|
||||
|
||||
// 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.color = safeAreaCol
|
||||
batch.color = if (IS_DEVELOPMENT_BUILD) safeAreaCol else colourNull
|
||||
App.fontGame.draw(it, thisIsDebugStr, 5f, App.scr.height - 24f)
|
||||
}
|
||||
}
|
||||
@@ -192,6 +194,7 @@ object TerrarumPostProcessor : Disposable {
|
||||
return outFBO
|
||||
}
|
||||
private val rng = HQRNG()
|
||||
private val colourNull = Color(0)
|
||||
|
||||
private fun Double.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.isClear = record.boolVal("clear")
|
||||
|
||||
prop.isPlatform = prop.tags.contains("PLATFORM")
|
||||
prop.isActorBlock = prop.tags.contains("ACTORBLOCK")
|
||||
prop.isPlatform = prop.hasTag("PLATFORM")
|
||||
prop.isActorBlock = prop.hasTag("ACTORBLOCK")
|
||||
|
||||
prop.isWallable = record.boolVal("wall")
|
||||
prop.maxSupport = record.intVal("grav")
|
||||
|
||||
@@ -75,6 +75,8 @@ class BlockProp {
|
||||
BlockCodex[BlockCodex.tileToVirtual[id]!![offset]]._lumCol.lane(channel)
|
||||
}
|
||||
|
||||
fun hasTag(s: String) = tags.contains(s)
|
||||
|
||||
/**
|
||||
* @param luminosity
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@ fun main() {
|
||||
// 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])
|
||||
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 bytes = ByteArray(TGA_HEADER_SIZE + texw * texh * 4 + 26)
|
||||
@@ -44,47 +44,50 @@ fun main() {
|
||||
println("Generating texture atlas ($texw x $texh)...")
|
||||
|
||||
// write pixels
|
||||
for (albedo0 in 0 until Skybox.albedoCnt) {
|
||||
val albedo = Skybox.albedos[albedo0]
|
||||
println("Albedo=$albedo")
|
||||
for (turb0 in 0 until Skybox.turbCnt) {
|
||||
val turbidity = Skybox.turbiditiesD[turb0]
|
||||
println("....... Turbidity=$turbidity")
|
||||
for (elev0 in 0 until Skybox.elevCnt) {
|
||||
val elevationDeg = Skybox.elevationsD[elev0]
|
||||
val elevationRad = Math.toRadians(elevationDeg)
|
||||
for (gammaPair in 0..1) {
|
||||
for (albedo0 in 0 until Skybox.albedoCnt) {
|
||||
val albedo = Skybox.albedos[albedo0]
|
||||
println("Albedo=$albedo")
|
||||
for (turb0 in 0 until Skybox.turbCnt) {
|
||||
val turbidity = Skybox.turbiditiesD[turb0]
|
||||
println("....... Turbidity=$turbidity")
|
||||
for (elev0 in 0 until Skybox.elevCnt) {
|
||||
val elevationDeg = Skybox.elevationsD[elev0]
|
||||
val elevationRad = Math.toRadians(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) {
|
||||
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)
|
||||
for (yp in 0 until Skybox.gradSize) {
|
||||
val yi = yp - 10
|
||||
val xf = -elevationDeg / 90.0
|
||||
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 *= -2.0 * asin(xf - 1.0) / PI
|
||||
if (elevationDeg < 0) yf *= Skybox.superellipsoidDecay(1.0 / 3.0, xf)
|
||||
val theta = yf * HALF_PI
|
||||
// vertical angle, where 0 is zenith, ±90 is ground (which is odd)
|
||||
if (elevationDeg < 0) yf *= Skybox.superellipsoidDecay(1.0 / 3.0, xf)
|
||||
val theta = yf * HALF_PI
|
||||
// vertical angle, where 0 is zenith, ±90 is ground (which is odd)
|
||||
|
||||
// println("$yp\t$theta")
|
||||
|
||||
val xyz = CIEXYZ(
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 0).toFloat(),
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 1).toFloat(),
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 2).toFloat()
|
||||
)
|
||||
val xyz2 = xyz.scaleToFit(elevationDeg)
|
||||
val rgb = xyz2.toRGB().toColor()
|
||||
val colour = rgb.toIntBits().toLittle()
|
||||
val xyz = CIEXYZ(
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, (gammaPair * 2f + 1f) * HALF_PI, 0).toFloat(),
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, (gammaPair * 2f + 1f) * HALF_PI, 1).toFloat(),
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, (gammaPair * 2f + 1f) * HALF_PI, 2).toFloat()
|
||||
)
|
||||
val xyz2 = xyz.scaleToFit(elevationDeg)
|
||||
val rgb = xyz2.toRGB().toColor()
|
||||
val colour = rgb.toIntBits().toLittle()
|
||||
|
||||
val imgOffX = (albedo0 * Skybox.elevCnt + elev0)
|
||||
val imgOffY = texh - 1 - (Skybox.gradSize * turb0 + yp)
|
||||
val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX)
|
||||
for (i in 0..3) {
|
||||
bytes[fileOffset + i] = colour[bytesLut[i]]
|
||||
val imgOffX = albedo0 * Skybox.elevCnt + elev0 + Skybox.elevCnt * Skybox.albedoCnt * gammaPair
|
||||
val imgOffY = texh - 1 - (Skybox.gradSize * turb0 + yp)
|
||||
val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX)
|
||||
for (i in 0..3) {
|
||||
bytes[fileOffset + i] = colour[bytesLut[i]]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,7 +96,7 @@ fun main() {
|
||||
|
||||
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
|
||||
@@ -13,6 +13,8 @@ import net.torvald.parametricsky.ArHosekSkyModel
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.abs
|
||||
import net.torvald.terrarum.floorToInt
|
||||
import net.torvald.terrarum.toInt
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import kotlin.math.*
|
||||
|
||||
@@ -25,7 +27,7 @@ object Skybox : Disposable {
|
||||
private const val PI = 3.141592653589793
|
||||
private const val TWO_PI = 6.283185307179586
|
||||
|
||||
const val gradSize = 64
|
||||
const val gradSize = 78
|
||||
|
||||
private lateinit var gradTexBinLowAlbedo: Array<TextureRegion>
|
||||
private lateinit var gradTexBinHighAlbedo: Array<TextureRegion>
|
||||
@@ -37,6 +39,7 @@ object Skybox : Disposable {
|
||||
fun loadlut() {
|
||||
tex = Texture(Gdx.files.internal("assets/clut/skybox.png"))
|
||||
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)
|
||||
texStripRegions = TextureRegionPack(tex, elevCnt, gradSize - 2, 0, 2, 0, 1)
|
||||
}
|
||||
@@ -50,28 +53,67 @@ object Skybox : Disposable {
|
||||
}*/
|
||||
|
||||
// use external LUT
|
||||
operator fun get(elevationDeg: Double, turbidity: Double, albedo: Double): TextureRegion {
|
||||
val elev = elevationDeg.coerceIn(-elevMax, elevMax).roundToInt().plus(elevMax).roundToInt()
|
||||
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)
|
||||
operator fun get(elevationDeg: Double, turbidity: Double, albedo: Double, isAfternoon: Boolean): TextureRegion {
|
||||
TODO()
|
||||
}
|
||||
|
||||
fun getUV(elevationDeg: Double, turbidity: Double, albedo: Double): Pair<Texture, FloatArray> {
|
||||
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()
|
||||
val region = texStripRegions.get(alb, turb)
|
||||
data class SkyboxRenderInfo(
|
||||
val texture: Texture,
|
||||
val uvs: FloatArray,
|
||||
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(
|
||||
u,
|
||||
region.v,
|
||||
u,
|
||||
region.v2
|
||||
val regionA = texStripRegions.get(albLo + albedoCnt * 0, turbLo)
|
||||
val regionB = texStripRegions.get(albLo + albedoCnt * 1, turbLo)
|
||||
val regionC = texStripRegions.get(albLo + albedoCnt * 0, turbHi)
|
||||
val regionD = texStripRegions.get(albLo + albedoCnt * 1, turbHi)
|
||||
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 {
|
||||
val deg1 = (-elevationDeg / elevMax).pow(0.93).times(-elevMax)
|
||||
val elevation1 = -deg1
|
||||
val elevation2 = -deg1 / 28.5
|
||||
val scale = (1f - (1f - 1f / 1.8.pow(elevation1)) * 0.97f).toFloat()
|
||||
val scale2 = (1.0 - (elevation2.pow(E) / E.pow(elevation2))*0.8).toFloat()
|
||||
// maths model: https://www.desmos.com/calculator/cwi7iyzygg
|
||||
|
||||
val x = -elevationDeg.toFloat()
|
||||
// val elevation2 = elevationDeg.toFloat() / 28.5f
|
||||
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(
|
||||
this.X.scaleFun() * scale * scale2,
|
||||
this.Y.scaleFun() * scale * scale2,
|
||||
this.Z.scaleFun() * scale * scale2,
|
||||
this.X.scaleFun() * f * h,
|
||||
this.Y.scaleFun() * f * h,
|
||||
this.Z.scaleFun() * f * h,
|
||||
this.alpha
|
||||
)
|
||||
}
|
||||
@@ -105,15 +152,13 @@ object Skybox : Disposable {
|
||||
val elevations = (0..150)
|
||||
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 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 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 turbCnt = turbidities.count()
|
||||
val albedoCnt = albedos.size
|
||||
val albedoLow = 0.1
|
||||
val albedoHight = 0.8 // for theoretical "winter wonderland"?
|
||||
val gamma = HALF_PI
|
||||
|
||||
internal fun Double.mapCircle() = sin(HALF_PI * this)
|
||||
@@ -121,8 +166,7 @@ object Skybox : Disposable {
|
||||
internal fun initiate() {
|
||||
printdbg(this, "Initialising skybox model")
|
||||
|
||||
gradTexBinLowAlbedo = getTexturmaps(albedoLow)
|
||||
gradTexBinHighAlbedo = getTexturmaps(albedoHight)
|
||||
TODO()
|
||||
|
||||
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
|
||||
*
|
||||
* 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 {
|
||||
val x = x0 - 0.5
|
||||
@@ -198,7 +247,7 @@ object Skybox : Disposable {
|
||||
// printdbg(this, "elev $elevationDeg turb $turbidity")
|
||||
|
||||
for (yp in 0 until gradSize) {
|
||||
val yi = yp - 3
|
||||
val yi = yp - 10
|
||||
val xf = -elevationDeg / 90.0
|
||||
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("hash: $hashedPwd")
|
||||
|
||||
if ("09ccf5067db6f58265b004829e33e715e819ba0984f1e1fcef49c36fcd5f745f".equals(hashedPwd, ignoreCase = true)) {
|
||||
if ("2d962f949f55906ac47f16095ded190c9e44d95920259b8f36c2e54bd75df173".equals(hashedPwd, ignoreCase = true)) {
|
||||
// beedle
|
||||
val msg = if (a) "Locked" else "Authenticated"
|
||||
Echo(msg)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -145,6 +145,9 @@ class Hitbox {
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the hitbox centred around the "canonical" point.
|
||||
*/
|
||||
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_2 = sx_1 + 0.5w_1 - 0.5w_2 // move variables to right-hand side to derive final value sx_2
|
||||
|
||||
@@ -359,6 +359,8 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
|
||||
return this
|
||||
}
|
||||
|
||||
fun hasTag(s: String) = tags.contains(s)
|
||||
|
||||
|
||||
companion object {
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
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.sin
|
||||
|
||||
|
||||
/**
|
||||
@@ -57,8 +56,10 @@ import kotlin.math.sin
|
||||
*/
|
||||
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. */
|
||||
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 {
|
||||
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
|
||||
|
||||
// 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 {
|
||||
/** 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 EPOCH_YEAR = 125
|
||||
const val EPOCH_YEAR = 1
|
||||
|
||||
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
|
||||
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) {
|
||||
@@ -228,27 +240,30 @@ class WorldTime(initTime: Long = 0L) {
|
||||
TIME_T += t
|
||||
}
|
||||
|
||||
val dayName: String
|
||||
get() = DAY_NAMES[dayOfWeek]
|
||||
|
||||
fun Long.toPositiveInt() = this.and(0x7FFFFFFF).toInt()
|
||||
fun Long.abs() = Math.abs(this)
|
||||
|
||||
/** Format: "%A, %Y %B %d %X" */
|
||||
fun getFormattedTime() = "${getDayNameShort()}, " +
|
||||
"$years " +
|
||||
"${getMonthNameFull()} " +
|
||||
"$calendarDay " +
|
||||
"${String.format("%02d", hours)}:" +
|
||||
"${String.format("%02d", minutes)}:" +
|
||||
"${String.format("%02d", seconds)}"
|
||||
/** Format: "ɣ%Y %B %d %A, %X" */
|
||||
fun getFormattedTime() =
|
||||
"ɣ$years " +
|
||||
"${getMonthNameFull()} " +
|
||||
"$calendarDay " +
|
||||
"${getDayNameFull()}, " +
|
||||
"${String.format("%02d", hours)}:" +
|
||||
"${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 getFilenameTime() = "${years.toString().padStart(4, '0')}${calendarMonth.toString().padStart(2, '0')}${calendarDay.toString().padStart(2, '0')}"
|
||||
|
||||
fun getDayNameFull() = DAY_NAMES[dayOfWeek]
|
||||
fun getDayNameShort() = DAY_NAMES_SHORT[dayOfWeek]
|
||||
fun getMonthNameFull() = MONTH_NAMES[calendarMonth - 1]
|
||||
fun getMonthNameShort() = MONTH_NAMES_SHORT[calendarMonth - 1]
|
||||
fun getDayNameFull() = getDayName(dayOfWeek)
|
||||
fun getDayNameShort() = getDayNameShort(dayOfWeek)
|
||||
fun getMonthNameFull() = getMonthName(calendarMonth)
|
||||
fun getMonthNameShort() = getMonthNameShort(calendarMonth)
|
||||
|
||||
override fun toString() = getFormattedTime()
|
||||
}
|
||||
@@ -152,6 +152,15 @@ object Lang {
|
||||
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
|
||||
*/
|
||||
|
||||
@@ -4,11 +4,10 @@ import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.graphics.*
|
||||
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.ShaderProgram
|
||||
import com.badlogic.gdx.utils.Disposable
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.*
|
||||
@@ -53,20 +52,20 @@ object IngameRenderer : Disposable {
|
||||
private lateinit var blurWriteQuad2: Mesh
|
||||
// private lateinit var blurWriteQuad4: Mesh
|
||||
|
||||
private lateinit var lightmapFbo: FloatFrameBuffer
|
||||
private lateinit var fboRGB: FloatFrameBuffer
|
||||
private lateinit var fboRGB_lightMixed: FloatFrameBuffer
|
||||
private lateinit var fboA: FloatFrameBuffer
|
||||
private lateinit var fboA_lightMixed: FloatFrameBuffer
|
||||
private lateinit var fboMixedOut: FloatFrameBuffer
|
||||
private lateinit var lightmapFbo: Float16FrameBuffer
|
||||
private lateinit var fboRGB: Float16FrameBuffer
|
||||
private lateinit var fboRGB_lightMixed: Float16FrameBuffer
|
||||
private lateinit var fboA: Float16FrameBuffer
|
||||
private lateinit var fboA_lightMixed: Float16FrameBuffer
|
||||
private lateinit var fboMixedOut: Float16FrameBuffer
|
||||
private lateinit var rgbTex: TextureRegion
|
||||
private lateinit var aTex: TextureRegion
|
||||
private lateinit var mixedOutTex: TextureRegion
|
||||
private lateinit var lightTex: TextureRegion
|
||||
private lateinit var blurTex: TextureRegion
|
||||
|
||||
private lateinit var fboBlurHalf: FloatFrameBuffer
|
||||
// private lateinit var fboBlurQuarter: FloatFrameBuffer
|
||||
private lateinit var fboBlurHalf: Float16FrameBuffer
|
||||
// private lateinit var fboBlurQuarter: Float16FrameBuffer
|
||||
|
||||
// you must have lightMixed FBO; otherwise you'll be reading from unbaked FBO and it freaks out GPU
|
||||
|
||||
@@ -694,7 +693,7 @@ object IngameRenderer : Disposable {
|
||||
|
||||
private const val KAWASE_POWER = 1.5f
|
||||
|
||||
fun processNoBlur(outFbo: FloatFrameBuffer) {
|
||||
fun processNoBlur(outFbo: Float16FrameBuffer) {
|
||||
|
||||
blurtex0.dispose()
|
||||
|
||||
@@ -710,7 +709,7 @@ object IngameRenderer : Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
fun processKawaseBlur(outFbo: FloatFrameBuffer) {
|
||||
fun processKawaseBlur(outFbo: Float16FrameBuffer) {
|
||||
|
||||
blurtex0.dispose()
|
||||
|
||||
@@ -807,12 +806,12 @@ object IngameRenderer : Disposable {
|
||||
//fboBlurQuarter.dispose()
|
||||
}
|
||||
|
||||
fboRGB = FloatFrameBuffer(width, height, false)
|
||||
fboRGB_lightMixed = FloatFrameBuffer(width, height, false)
|
||||
fboA = FloatFrameBuffer(width, height, false)
|
||||
fboA_lightMixed = FloatFrameBuffer(width, height, false)
|
||||
fboMixedOut = FloatFrameBuffer(width, height, false)
|
||||
lightmapFbo = FloatFrameBuffer(
|
||||
fboRGB = Float16FrameBuffer(width, height, false)
|
||||
fboRGB_lightMixed = Float16FrameBuffer(width, height, false)
|
||||
fboA = Float16FrameBuffer(width, height, false)
|
||||
fboA_lightMixed = Float16FrameBuffer(width, height, false)
|
||||
fboMixedOut = Float16FrameBuffer(width, height, false)
|
||||
lightmapFbo = Float16FrameBuffer(
|
||||
LightmapRenderer.lightBuffer.width * LightmapRenderer.DRAW_TILE_SIZE.toInt(),
|
||||
LightmapRenderer.lightBuffer.height * LightmapRenderer.DRAW_TILE_SIZE.toInt(),
|
||||
false
|
||||
@@ -823,13 +822,13 @@ object IngameRenderer : Disposable {
|
||||
blurTex = TextureRegion()
|
||||
mixedOutTex = TextureRegion(fboMixedOut.colorBufferTexture)
|
||||
|
||||
fboBlurHalf = FloatFrameBuffer(
|
||||
fboBlurHalf = Float16FrameBuffer(
|
||||
LightmapRenderer.lightBuffer.width * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 2,
|
||||
LightmapRenderer.lightBuffer.height * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 2,
|
||||
false
|
||||
)
|
||||
|
||||
/*fboBlurQuarter = FloatFrameBuffer(
|
||||
/*fboBlurQuarter = Float16FrameBuffer(
|
||||
LightmapRenderer.lightBuffer.width * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 4,
|
||||
LightmapRenderer.lightBuffer.height * LightmapRenderer.DRAW_TILE_SIZE.toInt() / 4,
|
||||
false
|
||||
|
||||
@@ -8,7 +8,7 @@ import com.badlogic.gdx.graphics.OrthographicCamera
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
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 net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.*
|
||||
@@ -147,7 +147,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
internal lateinit var uiRemoCon: UIRemoCon
|
||||
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 warningAppleRosettaIcon = TextureRegion(Texture(Gdx.files.internal("assets/graphics/gui/apple_rosetta_warning.tga")))
|
||||
@@ -262,7 +262,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
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
|
||||
printdbg(this, "update list of savegames")
|
||||
|
||||
@@ -14,16 +14,21 @@ import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||
*/
|
||||
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>) {
|
||||
if (args.size == 1) {
|
||||
printUsage()
|
||||
}
|
||||
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 {
|
||||
if (targetID == 0) tryTargetActivePlayer()
|
||||
val actor = getActor()
|
||||
if (actor != null) {
|
||||
when (args[1]) {
|
||||
@@ -36,7 +41,7 @@ internal object Inventory : ConsoleCommand {
|
||||
}
|
||||
}
|
||||
else {
|
||||
Echo("Actor $targetID is not Pocketed or does not exists")
|
||||
Echo("Actor $targetID is not Pocketed or does not exist")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarum.gameactors.faction.Faction
|
||||
import net.torvald.terrarum.gameitems.GameItem
|
||||
import net.torvald.terrarum.itemproperties.Material
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
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_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 isDownDown = false; protected set
|
||||
var downDownVirtually = false; internal set
|
||||
var downButtonHeld = 0; internal set
|
||||
var isLeftDown = false; protected set
|
||||
var isRightDown = false; protected set
|
||||
var isJumpDown = false; protected set
|
||||
@@ -221,7 +222,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
||||
if (isNoClip) {
|
||||
//grounded = true
|
||||
// platformToIgnore = null
|
||||
downDownVirtually = false
|
||||
downButtonHeld = 0
|
||||
}
|
||||
|
||||
// reset control box of AI
|
||||
@@ -248,6 +249,9 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
||||
}
|
||||
}
|
||||
|
||||
private val downDownMinLength: Int
|
||||
get() = (downDownMinLengthBase * (gravitation.y.abs() / 9.8).sqrt()).ceilToInt()
|
||||
|
||||
private fun updateGamerControlBox() {
|
||||
if (isGamer) {
|
||||
isUpDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_up"))
|
||||
@@ -288,17 +292,14 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
||||
}
|
||||
|
||||
// platform-related hacks
|
||||
// allow latching down downDownVirtually only when standing on a platform AND not jumping upwards
|
||||
val occupyingTileHasPlatform = bodyTiles.filterNotNull().any { it.isPlatform }
|
||||
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 (isDownDown || downButtonHeld in 1 until downDownMinLength) {
|
||||
downButtonHeld += 1
|
||||
}
|
||||
if (downDownVirtually && !occupyingTileHasPlatform && !feetTileIsAllPlatform) {
|
||||
downDownVirtually = false
|
||||
else {
|
||||
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
|
||||
|
||||
@@ -248,7 +248,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
forEachBlockbox { x, y, _, _ ->
|
||||
if (!hasCollision) {
|
||||
val tile = world!!.getTileFromTerrain(x, y)
|
||||
if (BlockCodex[tile].isSolid || BlockCodex[tile].isActorBlock) {
|
||||
if (!BlockCodex[tile].hasTag("INCONSEQUENTIAL")) {
|
||||
hasCollision = true
|
||||
}
|
||||
}
|
||||
@@ -311,7 +311,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
forEachBlockbox { x, y, _, _ ->
|
||||
if (!hasCollision) {
|
||||
val tile = world!!.getTileFromTerrain(x, y)
|
||||
if (BlockCodex[tile].isSolid || BlockCodex[tile].isActorBlock) {
|
||||
if (!BlockCodex[tile].hasTag("INCONSEQUENTIAL")) {
|
||||
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
|
||||
if (isWall && BlockCodex[wallUnderCursor].isSolid ||
|
||||
!isWall && (BlockCodex[terrainUnderCursor].isSolid || BlockCodex[terrainUnderCursor].isActorBlock))
|
||||
!isWall && !BlockCodex[terrainUnderCursor].hasTag("INCONSEQUENTIAL"))
|
||||
return@mouseInInteractableRange -1L
|
||||
|
||||
// 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 //
|
||||
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 actor = DiskEntry(it.referenceID.toLong(), ROOT, creation_t, time_t, actorContent)
|
||||
|
||||
@@ -56,10 +56,10 @@ object ControlPanelCommon {
|
||||
|
||||
val initialSel = optionsList.indexOf(App.getConfigString(optionName))
|
||||
|
||||
println("labelFuns = ${labelFuns.map { it.invoke() }}")
|
||||
println("optionsList = $optionsList")
|
||||
println("optionName = $optionName; value = ${App.getConfigString(optionName)}")
|
||||
println("initialSel = $initialSel")
|
||||
// println("labelFuns = ${labelFuns.map { it.invoke() }}")
|
||||
// println("optionsList = $optionsList")
|
||||
// println("optionName = $optionName; value = ${App.getConfigString(optionName)}")
|
||||
// println("initialSel = $initialSel")
|
||||
|
||||
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,")) {
|
||||
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 = {
|
||||
|
||||
@@ -17,6 +17,10 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
*/
|
||||
class UIBasicInfo() : UICanvas() {
|
||||
|
||||
init {
|
||||
handler.allowESCtoClose = false
|
||||
}
|
||||
|
||||
val player: ActorHumanoid?
|
||||
get() = Terrarum.ingame?.actorNowPlaying
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@ import net.torvald.terrarum.ui.UICanvas
|
||||
*/
|
||||
class UICheatDetected : UICanvas() {
|
||||
|
||||
init {
|
||||
handler.allowESCtoClose = false
|
||||
}
|
||||
|
||||
override var width: Int
|
||||
get() = App.scr.width
|
||||
set(value) { throw UnsupportedOperationException() }
|
||||
|
||||
@@ -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
|
||||
player.itemList.filter { (itm, 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 {
|
||||
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
|
||||
// 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
|
||||
(it.keyMode == CraftingCodex.CraftingItemKeyMode.TAG && gameItem.tags.contains(it.key))
|
||||
(it.keyMode == CraftingCodex.CraftingItemKeyMode.TAG && gameItem.hasTag(it.key))
|
||||
}.let {
|
||||
if (it.size > 1)
|
||||
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 {
|
||||
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)
|
||||
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
|
||||
val selectedItem = playerInventory.itemList.filter { (itm, 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})")
|
||||
selectedItem
|
||||
|
||||
@@ -24,18 +24,18 @@ class UIGraphicsControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
||||
init {
|
||||
ControlPanelCommon.register(this, width, "basegame.graphicscontrolpanel", arrayOf(
|
||||
arrayOf("", { Lang["CREDITS_VFX"] }, "h1"),
|
||||
arrayOf("fx_dither", { Lang["MENU_OPTIONS_DITHER"] }, "toggle"),
|
||||
arrayOf("fx_backgroundblur", { Lang["MENU_OPTIONS_BLUR"] }, "toggle"),
|
||||
arrayOf("maxparticles", { Lang["MENU_OPTIONS_PARTICLES"] }, "spinner,256,1024,256"),
|
||||
arrayOf("fx_dither", { Lang["MENU_OPTIONS_DITHER"] }, "toggle"),
|
||||
arrayOf("fx_backgroundblur", { Lang["MENU_OPTIONS_BLUR"] }, "toggle"),
|
||||
arrayOf("maxparticles", { Lang["MENU_OPTIONS_PARTICLES"] }, "spinner,256,1024,256"),
|
||||
arrayOf("", { Lang["MENU_OPTIONS_DISPLAY"] }, "h1"),
|
||||
arrayOf("screenwidth,screenheight", { Lang["MENU_OPTIONS_RESOLUTION"] }, "typeinres"),
|
||||
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("displayfps", { Lang["MENU_LABEL_FRAMESPERSEC"] }, "spinner,0,300,2"),
|
||||
arrayOf("usevsync", { Lang["MENU_OPTIONS_VSYNC"] }, "toggle"),
|
||||
arrayOf("", { "(${Lang["MENU_LABEL_RESTART_REQUIRED"]})" }, "p"),
|
||||
arrayOf("screenwidth,screenheight", { Lang["MENU_OPTIONS_RESOLUTION"] }, "typeinres"),
|
||||
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("displayfps", { Lang["MENU_LABEL_FRAMESPERSEC"] }, "spinner,0,300,2"),
|
||||
arrayOf("usevsync", { Lang["MENU_OPTIONS_VSYNC"] }, "toggle"),
|
||||
arrayOf("", { "(${Lang["MENU_LABEL_RESTART_REQUIRED"]})" }, "p"),
|
||||
arrayOf("", { Lang["MENU_LABEL_STREAMING"] }, "h1"),
|
||||
arrayOf("fx_streamerslayout", { Lang["MENU_OPTIONS_STREAMERS_LAYOUT"] }, "toggle"),
|
||||
arrayOf("fx_streamerslayout", { Lang["MENU_OPTIONS_STREAMERS_LAYOUT"] }, "toggle"),
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,6 @@ class UIInventoryFull(
|
||||
//val INVENTORY_CELLS_OFFSET_Y: Int = 107 + (AppLoader.terrarumAppConfig.screenH - internalHeight) / 2
|
||||
|
||||
init {
|
||||
handler.allowESCtoClose = true
|
||||
}
|
||||
|
||||
private val SP = "\u3000 "
|
||||
|
||||
@@ -235,7 +235,7 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
|
||||
if (showSpinner) {
|
||||
val spin = spinner.get(spinnerFrame % 8, spinnerFrame / 8)
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,8 +90,17 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
listOf(NullUI/*, transitionalAutosave*/)
|
||||
)
|
||||
|
||||
internal fun queueUpManageScr() { transitionPanel.setCentreUIto(0) }
|
||||
internal fun queueUpNewCharScr() { transitionPanel.setCentreUIto(1) }
|
||||
private val nodesForListing = Yaml(UITitleRemoConYaml.injectedMenuSingleCharSel).parse()
|
||||
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 takeAutosaveSelectorDown() { transitionPanel.setRightUIto(0) }
|
||||
@@ -102,6 +111,10 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
|
||||
internal fun changePanelTo(index: Int) {
|
||||
transitionPanel.requestTransition(index)
|
||||
if (index == 1)
|
||||
remoCon.setNewRemoConContents(nodesForManage)
|
||||
else
|
||||
remoCon.setNewRemoConContents(nodesForListing)
|
||||
}
|
||||
|
||||
override fun advanceMode(button: UIItem) {
|
||||
@@ -118,6 +131,9 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
// takeAutosaveSelectorDown()
|
||||
transitionPanel.show()
|
||||
|
||||
nodesForListing.parent = remoCon.treeRoot
|
||||
nodesForManage.parent = remoCon.treeRoot
|
||||
|
||||
}
|
||||
|
||||
override fun hide() {
|
||||
|
||||
@@ -26,11 +26,14 @@ class UIPerformanceControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
||||
arrayOf("", { Lang["MENU_OPTIONS_GAMEPLAY"] }, "h1"),
|
||||
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("", { 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("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("", { "(${Lang["MENU_LABEL_RESTART_REQUIRED"]})" }, "p"),
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override var height = ControlPanelCommon.getMenuHeight("basegame.performancecontrolpanel")
|
||||
|
||||
@@ -18,6 +18,11 @@ import kotlin.math.roundToInt
|
||||
* Created by minjaesong on 2016-07-20.
|
||||
*/
|
||||
class UIQuickslotBar : UICanvas() {
|
||||
|
||||
init {
|
||||
handler.allowESCtoClose = false
|
||||
}
|
||||
|
||||
private val cellSize = ItemSlotImageFactory.slotImage.tileW // 38
|
||||
|
||||
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.
|
||||
*/
|
||||
class UIQuickslotPie : UICanvas() {
|
||||
|
||||
init {
|
||||
handler.allowESCtoClose = false
|
||||
}
|
||||
|
||||
private val cellSize = ItemSlotImageFactory.slotImage.tileW
|
||||
|
||||
private val slotCount = UIQuickslotBar.SLOT_COUNT
|
||||
|
||||
@@ -21,6 +21,10 @@ class UIScreenZoom : UICanvas(
|
||||
App.getConfigInt("control_key_zoom")
|
||||
) {
|
||||
|
||||
init {
|
||||
handler.allowESCtoClose = false
|
||||
}
|
||||
|
||||
val zoomText = "${getKeycapPC(handler.toggleKeyLiteral!!)} $EMDASH Zoom Out"
|
||||
|
||||
override var width = App.fontGame.getWidth(zoomText)
|
||||
|
||||
@@ -41,6 +41,7 @@ object UITitleRemoConYaml {
|
||||
|
||||
// todo add MENU_IO_IMPORT
|
||||
val injectedMenuSingleCharSel = """
|
||||
- MENU_IO_IMPORT
|
||||
- CONTEXT_CHARACTER_NEW : net.torvald.terrarum.modulebasegame.ui.UINewCharacter
|
||||
- MENU_LABEL_RETURN
|
||||
"""
|
||||
@@ -48,6 +49,12 @@ object UITitleRemoConYaml {
|
||||
val injectedMenuSingleWorldSel = """
|
||||
- CONTEXT_WORLD_NEW : net.torvald.terrarum.modulebasegame.ui.UINewWorld
|
||||
- MENU_LABEL_RETURN
|
||||
"""
|
||||
|
||||
val injectedMenuSingleSaveManage = """
|
||||
- MENU_MODULES
|
||||
- MENU_LABEL_PREV_SAVES
|
||||
- MENU_LABEL_RETURN
|
||||
"""
|
||||
|
||||
operator fun invoke(hasSave: Boolean) =
|
||||
|
||||
@@ -14,6 +14,10 @@ import net.torvald.terrarum.ui.UICanvas
|
||||
*/
|
||||
class UITooltip : UICanvas() {
|
||||
|
||||
init {
|
||||
handler.allowESCtoClose = false
|
||||
}
|
||||
|
||||
override var openCloseTime: Second = 0f
|
||||
|
||||
private val tooltipBackCol = Color.WHITE
|
||||
|
||||
@@ -21,6 +21,10 @@ class UIVitalMetre(
|
||||
val order: Int
|
||||
) : UICanvas() {
|
||||
|
||||
init {
|
||||
handler.allowESCtoClose = false
|
||||
}
|
||||
|
||||
init {
|
||||
// semitransparent
|
||||
color?.a = 0.91f
|
||||
|
||||
385
src/net/torvald/terrarum/modulebasegame/ui/UIWallCalendar.kt
Normal file
385
src/net/torvald/terrarum/modulebasegame/ui/UIWallCalendar.kt
Normal file
@@ -0,0 +1,385 @@
|
||||
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.App
|
||||
import net.torvald.terrarum.INGAME
|
||||
import net.torvald.terrarum.RunningEnvironment
|
||||
import net.torvald.terrarum.floorToInt
|
||||
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 = App.getConfigInt("control_key_inventory"),
|
||||
toggleButtonLiteral = App.getConfigInt("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(App.getConfigInt("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() {
|
||||
}
|
||||
}
|
||||
@@ -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.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, "$MASS$ccG${player.mass.toString().padEnd(8).substring(0,8)}", gap + 7f*(jX + 13), line(jY+1))
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.badlogic.gdx.graphics.*
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
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.jme3.math.FastMath
|
||||
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 shaderBoxUp = App.loadShaderFromClasspath("shaders/default.vert", "shaders/boxup.frag")
|
||||
|
||||
private lateinit var fboBlur: FloatFrameBuffer
|
||||
private lateinit var fboBlurHalf: FloatFrameBuffer
|
||||
private lateinit var fboBlurQuarter: FloatFrameBuffer
|
||||
private lateinit var fboBlur: Float16FrameBuffer
|
||||
private lateinit var fboBlurHalf: Float16FrameBuffer
|
||||
private lateinit var fboBlurQuarter: Float16FrameBuffer
|
||||
private lateinit var blurWriteQuad: Mesh
|
||||
private lateinit var blurWriteQuad2: Mesh
|
||||
private lateinit var blurWriteQuad4: Mesh
|
||||
@@ -326,17 +326,17 @@ object Toolkit : Disposable {
|
||||
val fw = App.scr.width//MathUtils.nextPowerOfTwo(App.scr.width)
|
||||
val fh = App.scr.height//MathUtils.nextPowerOfTwo(App.scr.height)
|
||||
|
||||
fboBlur = FloatFrameBuffer(
|
||||
fboBlur = Float16FrameBuffer(
|
||||
fw,
|
||||
fh,
|
||||
false
|
||||
)
|
||||
fboBlurHalf = FloatFrameBuffer(
|
||||
fboBlurHalf = Float16FrameBuffer(
|
||||
fw / 2,
|
||||
fh / 2,
|
||||
false
|
||||
)
|
||||
fboBlurQuarter = FloatFrameBuffer(
|
||||
fboBlurQuarter = Float16FrameBuffer(
|
||||
fw / 4,
|
||||
fh / 4,
|
||||
false
|
||||
|
||||
@@ -30,7 +30,7 @@ class UIHandler(//var UI: UICanvas,
|
||||
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
||||
var customPositioning: Boolean = false, // mainly used by vital meter
|
||||
var doNotWarnConstant: Boolean = false,
|
||||
internal var allowESCtoClose: Boolean = false,
|
||||
internal var allowESCtoClose: Boolean = true,
|
||||
var uiTogglerFunctionDefault: ((UIHandler) -> Unit)? = null
|
||||
): Disposable {
|
||||
|
||||
@@ -214,7 +214,7 @@ void main() {
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,15 +17,15 @@ import kotlin.math.roundToInt
|
||||
*/
|
||||
|
||||
class UIItemSpinner(
|
||||
parentUI: UICanvas,
|
||||
initialX: Int, initialY: Int,
|
||||
private var initialValue: Number,
|
||||
val min: Number,
|
||||
val max: Number,
|
||||
val step: Number,
|
||||
override val width: Int,
|
||||
private val drawBorder: Boolean = true,
|
||||
private val numberToTextFunction: (Number) -> String = { "$it" }
|
||||
parentUI: UICanvas,
|
||||
initialX: Int, initialY: Int,
|
||||
private var initialValue: Number,
|
||||
val min: Number,
|
||||
val max: Number,
|
||||
val step: Number,
|
||||
override val width: Int,
|
||||
private val drawBorder: Boolean = true,
|
||||
private val numberToTextFunction: (Number) -> String = { "$it" }
|
||||
) : UIItem(parentUI, initialX, initialY) {
|
||||
|
||||
// to alleviate floating point errors adding up as the spinner is being used
|
||||
|
||||
@@ -17,13 +17,14 @@ import net.torvald.terrarum.gameworld.fmod
|
||||
* Created by minjaesong on 2021-10-21.
|
||||
*/
|
||||
class UIItemTextSelector(
|
||||
parentUI: UICanvas,
|
||||
initialX: Int, initialY: Int,
|
||||
val labelfuns: List<() -> String>,
|
||||
initialSelection: Int,
|
||||
override val width: Int,
|
||||
private val drawBorder: Boolean = true,
|
||||
private val clickToShowPalette: Boolean = true
|
||||
parentUI: UICanvas,
|
||||
initialX: Int, initialY: Int,
|
||||
val labelfuns: List<() -> String>,
|
||||
initialSelection: Int,
|
||||
override val width: Int,
|
||||
private val drawBorder: Boolean = true,
|
||||
private val clickToShowPalette: Boolean = true,
|
||||
private val useSpinnerButtons: Boolean = false,
|
||||
) : UIItem(parentUI, initialX, initialY) {
|
||||
|
||||
init {
|
||||
@@ -127,6 +128,9 @@ class UIItemTextSelector(
|
||||
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) {
|
||||
labelCache = labelfuns.map { it() }
|
||||
|
||||
@@ -184,12 +188,12 @@ class UIItemTextSelector(
|
||||
// left button icon
|
||||
batch.color = if (mouseOnButton == 1 && mousePushed) Toolkit.Theme.COL_SELECTED
|
||||
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
|
||||
batch.color = if (mouseOnButton == 2 && mousePushed) Toolkit.Theme.COL_SELECTED
|
||||
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
|
||||
if (!paletteShowing) {
|
||||
|
||||
@@ -154,8 +154,8 @@ internal object WeatherMixer : RNGConsumer {
|
||||
|
||||
}
|
||||
|
||||
var turbidity = 4.0; private set
|
||||
private var gH = 1.4f * App.scr.height
|
||||
var turbidity = 1.0; private set
|
||||
private var gH = 1.8f * App.scr.height
|
||||
// private var gH = 0.8f * App.scr.height
|
||||
|
||||
internal var parallaxPos = 0f; private set
|
||||
@@ -168,9 +168,11 @@ internal object WeatherMixer : RNGConsumer {
|
||||
drawSkybox(camera, batch, world)
|
||||
}
|
||||
|
||||
private val parallaxDomainSize = 400f
|
||||
private val turbidityDomainSize = 533.3333f
|
||||
|
||||
private fun drawSkybox(camera: Camera, batch: FlippingSpriteBatch, world: GameWorld) {
|
||||
val parallaxZeroPos = (world.height / 3f)
|
||||
val parallaxDomainSize = 300f
|
||||
|
||||
// we will not care for nextSkybox for now
|
||||
val timeNow = (forceTimeAt ?: world.worldTime.TIME_T.toInt()) % WorldTime.DAY_LENGTH
|
||||
@@ -199,17 +201,20 @@ internal object WeatherMixer : RNGConsumer {
|
||||
-+ <- 0.0 =
|
||||
*/
|
||||
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
|
||||
// println(parallax) // parallax value works as intended.
|
||||
|
||||
gdxBlendNormalStraightAlpha()
|
||||
|
||||
turbidity = (3.5 + turbidityCoeff * 2.5).coerceIn(1.0, 6.0)
|
||||
val thisTurbidity = forceTurbidity ?: turbidity
|
||||
|
||||
// TODO trilinear with (deg, turb, alb)
|
||||
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)
|
||||
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
|
||||
@@ -220,20 +225,26 @@ internal object WeatherMixer : RNGConsumer {
|
||||
batch.inUse {
|
||||
batch.shader = shaderBlendMax
|
||||
shaderBlendMax.setUniformi("tex1", 1)
|
||||
shaderBlendMax.setUniformf("drawOffset", 0f, gradY)
|
||||
shaderBlendMax.setUniformf("drawOffsetSize", App.scr.wf, gH)
|
||||
shaderBlendMax.setUniform2fv("skyboxUV1", uvs, 0, 2)
|
||||
shaderBlendMax.setUniform2fv("skyboxUV2", uvs, 2, 2)
|
||||
shaderBlendMax.setUniformf("drawOffsetSize", 0f, gradY, App.scr.wf, gH)
|
||||
shaderBlendMax.setUniform4fv("uvA", uvs, 0, 4)
|
||||
shaderBlendMax.setUniform4fv("uvB", uvs, 4, 4)
|
||||
shaderBlendMax.setUniform4fv("uvC", uvs, 8, 4)
|
||||
shaderBlendMax.setUniform4fv("uvD", uvs, 12, 4)
|
||||
shaderBlendMax.setUniform4fv("uvE", uvs, 16, 4)
|
||||
shaderBlendMax.setUniform4fv("uvF", uvs, 20, 4)
|
||||
shaderBlendMax.setUniform4fv("uvG", uvs, 24, 4)
|
||||
shaderBlendMax.setUniform4fv("uvH", uvs, 28, 4)
|
||||
shaderBlendMax.setUniformf("texBlend", mornNoonBlend, turbX, albX, 0f)
|
||||
shaderBlendMax.setUniformf("astrumScroll", astrumOffX + astrumX, astrumOffY + astrumY)
|
||||
shaderBlendMax.setUniformf("randomNumber",
|
||||
// (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(23L) xor 1639L + 29L).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(-11.8f).plus(37L),
|
||||
world.worldTime.TIME_T.div(+11.9f).plus(23L),
|
||||
world.worldTime.TIME_T.div(-12.3f).plus(29L),
|
||||
world.worldTime.TIME_T.div(+14.1f).plus(31L),
|
||||
world.worldTime.TIME_T.div(-13.8f).plus(37L),
|
||||
world.worldTime.TIME_T.div(+13.9f).plus(23L),
|
||||
world.worldTime.TIME_T.div(-14.3f).plus(29L),
|
||||
)
|
||||
|
||||
batch.color = Color.WHITE
|
||||
|
||||
@@ -349,7 +349,7 @@ internal object BlocksDrawer {
|
||||
val tileNumber = if (thisTile == Block.AIR) 0
|
||||
// special case: actorblocks and F3 key
|
||||
else if (BlockCodex.hasProp(thisTile) && BlockCodex[thisTile].isActorBlock &&
|
||||
!BlockCodex[thisTile].tags.contains("DORENDER") && !KeyToggler.isOn(Keys.F3))
|
||||
!BlockCodex[thisTile].hasTag("DORENDER") && !KeyToggler.isOn(Keys.F3))
|
||||
0
|
||||
// special case: fluids
|
||||
else if (mode == FLUID)
|
||||
|
||||
@@ -6,7 +6,9 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.gdx.graphics.Cvec
|
||||
import net.torvald.gdx.graphics.PixmapIO2
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
@@ -15,6 +17,7 @@ import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.AtlasSource.*
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.math.sqrt
|
||||
|
||||
/**
|
||||
* This class implements work_files/dynamic_shape_2_0.psd
|
||||
@@ -28,13 +31,12 @@ import kotlin.math.roundToInt
|
||||
*/
|
||||
class CreateTileAtlas {
|
||||
|
||||
// min size 1024 = tile_size 16 * atlasCursor 64
|
||||
val MAX_TEX_SIZE = App.getConfigInt("atlastexsize").coerceIn(1024, App.glInfo.GL_MAX_TEXTURE_SIZE)
|
||||
val TILES_IN_X = MAX_TEX_SIZE / TILE_SIZE
|
||||
var MAX_TEX_SIZE = App.getConfigInt("atlastexsize").coerceIn(1024, App.glInfo.GL_MAX_TEXTURE_SIZE); private set
|
||||
var TILES_IN_X = MAX_TEX_SIZE / TILE_SIZE; private set
|
||||
|
||||
val SHADER_SIZE_KEYS = floatArrayOf(MAX_TEX_SIZE.toFloat(), MAX_TEX_SIZE.toFloat(), TILES_IN_X.toFloat(), TILES_IN_X.toFloat())
|
||||
var SHADER_SIZE_KEYS = floatArrayOf(MAX_TEX_SIZE.toFloat(), MAX_TEX_SIZE.toFloat(), TILES_IN_X.toFloat(), TILES_IN_X.toFloat()); private set
|
||||
|
||||
private val TOTAL_TILES = TILES_IN_X * TILES_IN_X
|
||||
private var TOTAL_TILES = TILES_IN_X * TILES_IN_X
|
||||
|
||||
val wallOverlayColour = Color(.65f, .65f, .65f, 1f)
|
||||
|
||||
@@ -66,12 +68,54 @@ class CreateTileAtlas {
|
||||
private val atlasInit = "./assets/graphics/blocks/init.tga"
|
||||
private var itemSheetCursor = 16
|
||||
|
||||
internal val itemTerrainPixmap = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
internal val itemTerrainPixmapGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
internal val itemWallPixmap = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
internal val itemWallPixmapGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
internal lateinit var itemTerrainPixmap: Pixmap
|
||||
internal lateinit var itemTerrainPixmapGlow: Pixmap
|
||||
internal lateinit var itemWallPixmap: Pixmap
|
||||
internal lateinit var itemWallPixmapGlow: Pixmap
|
||||
|
||||
|
||||
private fun drawInitPixmap() {
|
||||
val initPixmap = Pixmap(Gdx.files.internal(atlasInit))
|
||||
|
||||
val tilesInInitPixmap = (initPixmap.width * initPixmap.height) / (TILE_SIZE * TILE_SIZE)
|
||||
val tilesPossibleInCurrentPixmap = (atlas.width * atlas.height) / (TILE_SIZE * TILE_SIZE)
|
||||
|
||||
if (tilesInInitPixmap > tilesPossibleInCurrentPixmap) throw Error("Atlas size too small -- can't even fit the init.tga (MAX_TEX_SIZE must be at least ${FastMath.nextPowerOfTwo((sqrt(tilesInInitPixmap.toFloat()) * TILE_SIZE).ceilToInt())})")
|
||||
|
||||
if (MAX_TEX_SIZE >= initPixmap.width) {
|
||||
atlas.drawPixmap(initPixmap, 0, 0)
|
||||
atlasAutumn.drawPixmap(initPixmap, 0, 0)
|
||||
atlasWinter.drawPixmap(initPixmap, 0, 0)
|
||||
atlasSpring.drawPixmap(initPixmap, 0, 0)
|
||||
}
|
||||
else {
|
||||
/*
|
||||
What's happening:
|
||||
|
||||
src: dest:
|
||||
AAAABBBBCCCCDDDD AAAA
|
||||
BBBB
|
||||
CCCC
|
||||
DDDD
|
||||
*/
|
||||
val destX = 0
|
||||
val srcY = 0
|
||||
val scanW = MAX_TEX_SIZE
|
||||
val scanH = TILE_SIZE
|
||||
for (scantile in 0 until (initPixmap.width.toFloat() / MAX_TEX_SIZE).ceilToInt()) {
|
||||
val srcX = scantile * scanW
|
||||
val destY = scantile * TILE_SIZE
|
||||
|
||||
atlas.drawPixmap(initPixmap, srcX, srcY, scanW, scanH, destX, destY, scanW, scanH)
|
||||
atlasAutumn.drawPixmap(initPixmap, srcX, srcY, scanW, scanH, destX, destY, scanW, scanH)
|
||||
atlasWinter.drawPixmap(initPixmap, srcX, srcY, scanW, scanH, destX, destY, scanW, scanH)
|
||||
atlasSpring.drawPixmap(initPixmap, srcX, srcY, scanW, scanH, destX, destY, scanW, scanH)
|
||||
}
|
||||
}
|
||||
|
||||
initPixmap.dispose()
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be called AFTER mods' loading so that all the block props are loaded
|
||||
*/
|
||||
@@ -80,27 +124,17 @@ class CreateTileAtlas {
|
||||
tags = HashMap<ItemID, RenderTag>()
|
||||
itemSheetNumbers = HashMap<ItemID, Int>()
|
||||
|
||||
atlas = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
atlasAutumn = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
atlasWinter = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
atlasSpring = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
atlasFluid = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
atlasGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
|
||||
atlas.blending = Pixmap.Blending.None
|
||||
atlasAutumn.blending = Pixmap.Blending.None
|
||||
atlasWinter.blending = Pixmap.Blending.None
|
||||
atlasSpring.blending = Pixmap.Blending.None
|
||||
atlasFluid.blending = Pixmap.Blending.None
|
||||
atlasGlow.blending = Pixmap.Blending.None
|
||||
atlas = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||
atlasAutumn = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||
atlasWinter = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||
atlasSpring = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||
atlasFluid = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||
atlasGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||
|
||||
// populate the atlantes with atlasInit
|
||||
// this just directly copies the image to the atlantes :p
|
||||
val initPixmap = Pixmap(Gdx.files.internal(atlasInit))
|
||||
atlas.drawPixmap(initPixmap, 0, 0)
|
||||
atlasAutumn.drawPixmap(initPixmap, 0, 0)
|
||||
atlasWinter.drawPixmap(initPixmap, 0, 0)
|
||||
atlasSpring.drawPixmap(initPixmap, 0, 0)
|
||||
drawInitPixmap()
|
||||
|
||||
|
||||
// get all the files applicable
|
||||
// first, get all the '/blocks' directory, and add all the files, regardless of their extension, to the list
|
||||
@@ -135,8 +169,8 @@ class CreateTileAtlas {
|
||||
}
|
||||
|
||||
// test print
|
||||
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlas.tga"), atlas, false)
|
||||
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlasGlow.tga"), atlasGlow, false)
|
||||
// PixmapIO2.writeTGA(Gdx.files.absolute("${App.defaultDir}/atlas.tga"), atlas, false)
|
||||
// PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlasGlow.tga"), atlasGlow, false)
|
||||
|
||||
|
||||
|
||||
@@ -161,6 +195,11 @@ class CreateTileAtlas {
|
||||
// val itemTerrainPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
// val itemWallPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
|
||||
itemTerrainPixmap = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
itemTerrainPixmapGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
itemWallPixmap = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
itemWallPixmapGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||
|
||||
tags.toMap().forEach { id, tag ->
|
||||
val tilePosFromAtlas = tag.tileNumber + maskTypetoTileIDForItemImage(tag.maskType)
|
||||
val srcX = (tilePosFromAtlas % TILES_IN_X) * TILE_SIZE
|
||||
@@ -217,7 +256,6 @@ class CreateTileAtlas {
|
||||
itemWallTextureGlow = Texture(itemWallPixmapGlow)
|
||||
// itemTerrainPixmap.dispose()
|
||||
// itemWallPixmap.dispose()
|
||||
initPixmap.dispose()
|
||||
|
||||
initialised = true
|
||||
} }
|
||||
@@ -242,6 +280,7 @@ class CreateTileAtlas {
|
||||
val blockName = matte.nameWithoutExtension().split('-').last().toInt() // basically a filename
|
||||
val blockID = "$modname:$blockName"
|
||||
|
||||
|
||||
// determine the type of the block (populate tags list)
|
||||
// predefined by the image dimension: 16x16 for (1,0)
|
||||
if (tilesPixmap.width == TILE_SIZE && tilesPixmap.height == TILE_SIZE) {
|
||||
@@ -307,8 +346,10 @@ class CreateTileAtlas {
|
||||
}
|
||||
|
||||
private fun drawToAtlantes(matte: Pixmap, glow: Pixmap, tilesCount: Int) {
|
||||
if (atlasCursor >= TOTAL_TILES) {
|
||||
throw Error("Too much tiles for $MAX_TEX_SIZE texture size: $atlasCursor")
|
||||
if (atlasCursor + tilesCount >= TOTAL_TILES) {
|
||||
// throw Error("Too much tiles for $MAX_TEX_SIZE texture size: $atlasCursor")
|
||||
println("[CreateTileAtlas] Too much tiles for atlas of ${MAX_TEX_SIZE}x$MAX_TEX_SIZE (tiles so far: $atlasCursor/${(MAX_TEX_SIZE*MAX_TEX_SIZE)/(TILE_SIZE* TILE_SIZE)}, tiles to be added: $tilesCount), trying to expand the atlas...")
|
||||
expandAtlantes()
|
||||
}
|
||||
|
||||
val seasonal = matte.width == matte.height && matte.width == 14 * TILE_SIZE
|
||||
@@ -413,4 +454,60 @@ class CreateTileAtlas {
|
||||
private enum class AtlasSource {
|
||||
FOUR_SEASONS, SUMMER, AUTUMN, WINTER, SPRING, FLUID, GLOW
|
||||
}
|
||||
|
||||
private fun expandAtlantes() {
|
||||
if (MAX_TEX_SIZE >= App.glInfo.GL_MAX_TEXTURE_SIZE) {
|
||||
throw RuntimeException("Cannot expand atlas: texture size is already at its maximum possible size allowed by the graphics processor (${MAX_TEX_SIZE}x${MAX_TEX_SIZE})")
|
||||
}
|
||||
|
||||
val oldTexSize = MAX_TEX_SIZE
|
||||
val newTexSize = oldTexSize * 2
|
||||
|
||||
|
||||
MAX_TEX_SIZE = newTexSize
|
||||
TILES_IN_X = MAX_TEX_SIZE / TILE_SIZE
|
||||
SHADER_SIZE_KEYS = floatArrayOf(MAX_TEX_SIZE.toFloat(), MAX_TEX_SIZE.toFloat(), TILES_IN_X.toFloat(), TILES_IN_X.toFloat())
|
||||
TOTAL_TILES = TILES_IN_X * TILES_IN_X
|
||||
|
||||
|
||||
val newAtlantes = Array<Pixmap>(5) {
|
||||
Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also {
|
||||
it.blending = Pixmap.Blending.None
|
||||
it.filter = Pixmap.Filter.NearestNeighbour
|
||||
}
|
||||
}
|
||||
listOf(atlas, atlasAutumn, atlasWinter, atlasSpring, atlasGlow).forEachIndexed { index, pixmap ->
|
||||
/*
|
||||
How it works:
|
||||
|
||||
old: new:
|
||||
AAAAAAAA AAAAAAAABBBBBBBB
|
||||
BBBBBBBB CCCCCCCCDDDDDDDD
|
||||
CCCCCCCC ...
|
||||
DDDDDDDD
|
||||
...
|
||||
|
||||
*/
|
||||
for (scantile in 0 until pixmap.height / TILE_SIZE) {
|
||||
val srcX = 0
|
||||
val srcY = scantile * TILE_SIZE
|
||||
val destX = (scantile % 2) * oldTexSize
|
||||
val destY = (scantile / 2) * TILE_SIZE
|
||||
val scanW = pixmap.width
|
||||
val scanH = TILE_SIZE
|
||||
|
||||
newAtlantes[index].drawPixmap(pixmap, srcX, srcY, scanW, scanH, destX, destY, scanW, scanH)
|
||||
}
|
||||
pixmap.dispose()
|
||||
}
|
||||
|
||||
atlas = newAtlantes[0]
|
||||
atlasAutumn = newAtlantes[1]
|
||||
atlasWinter = newAtlantes[2]
|
||||
atlasSpring = newAtlantes[3]
|
||||
atlasGlow = newAtlantes[4]
|
||||
|
||||
|
||||
App.setConfig("atlastexsize", newTexSize)
|
||||
}
|
||||
}
|
||||
@@ -33,12 +33,12 @@ object FeaturesDrawer {
|
||||
TileSurvey.submitProposal(
|
||||
TileSurvey.SurveyProposal(
|
||||
"basegame.FeaturesDrawer.coldTiles", 72, 48, 2, 2
|
||||
) { world, x, y -> BlockCodex[world.getTileFromTerrain(x, y)].tags.contains("COLD") }
|
||||
) { world, x, y -> BlockCodex[world.getTileFromTerrain(x, y)].hasTag("COLD") }
|
||||
)
|
||||
TileSurvey.submitProposal(
|
||||
TileSurvey.SurveyProposal(
|
||||
"basegame.FeaturesDrawer.warmTiles", 72, 48, 2, 2
|
||||
) { world, x, y -> BlockCodex[world.getTileFromTerrain(x, y)].tags.contains("WARM") }
|
||||
) { world, x, y -> BlockCodex[world.getTileFromTerrain(x, y)].hasTag("WARM") }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
package org.dyn4j.geometry
|
||||
|
||||
import org.dyn4j.Epsilon
|
||||
import kotlin.math.sign
|
||||
|
||||
/**
|
||||
* This class represents a vector or point in 2D space.
|
||||
@@ -699,6 +700,9 @@ class Vector2 {
|
||||
return a
|
||||
}
|
||||
|
||||
val signum: Vector2
|
||||
get() = Vector2(this.x.sign, this.y.sign)
|
||||
|
||||
companion object {
|
||||
/** A vector representing the x-axis; this vector should not be changed at runtime; used internally */
|
||||
internal val X_AXIS = Vector2(1.0, 0.0)
|
||||
|
||||
@@ -13,10 +13,16 @@ out vec4 fragColor;
|
||||
|
||||
const vec2 boolean = vec2(0.0, 1.0);
|
||||
|
||||
uniform vec2 drawOffset; // value of the 'gradY'
|
||||
uniform vec2 drawOffsetSize; // value of the 'gradH'
|
||||
uniform vec2 skyboxUV1; // (u, v) for the skybox drawing
|
||||
uniform vec2 skyboxUV2; // (u2, v2) for the skybox drawing
|
||||
uniform vec4 drawOffsetSize; // (gradX, gradY, gradW, gradH)
|
||||
uniform vec4 uvA; // (u, v, u2, v2) for morn, turbLow, albLow
|
||||
uniform vec4 uvB; // (u, v, u2, v2) for noon, turbLow, albLow
|
||||
uniform vec4 uvC; // (u, v, u2, v2) for morn, turbHigh, albLow
|
||||
uniform vec4 uvD; // (u, v, u2, v2) for noon, turbHigh, albLow
|
||||
uniform vec4 uvE; // (u, v, u2, v2) for morn, turbLow, albHigh
|
||||
uniform vec4 uvF; // (u, v, u2, v2) for noon, turbLow, albHigh
|
||||
uniform vec4 uvG; // (u, v, u2, v2) for morn, turbHigh, albHigh
|
||||
uniform vec4 uvH; // (u, v, u2, v2) for noon, turbHigh, albHigh
|
||||
uniform vec4 texBlend; // (morn/noon, turbidity, albedo, unused)
|
||||
uniform vec2 tex1Size = vec2(4096.0);
|
||||
uniform vec2 astrumScroll = vec2(0.0);
|
||||
uniform vec4 randomNumber = vec4(1.0, -2.0, 3.0, -4.0);
|
||||
@@ -112,15 +118,36 @@ vec4 random(vec2 p) {
|
||||
|
||||
// draw call to this function must use UV coord of (0,0,1,1)!
|
||||
void main(void) {
|
||||
vec2 skyboxTexCoord = mix(skyboxUV1, skyboxUV2, v_texCoords);
|
||||
vec2 astrumTexCoord = (v_texCoords * drawOffsetSize + drawOffset + astrumScroll) / tex1Size;
|
||||
vec4 colorTexA = texture(u_texture, mix(uvA.xy, uvA.zw, v_texCoords));
|
||||
vec4 colorTexB = texture(u_texture, mix(uvB.xy, uvB.zw, v_texCoords));
|
||||
vec4 colorTexC = texture(u_texture, mix(uvC.xy, uvC.zw, v_texCoords));
|
||||
vec4 colorTexD = texture(u_texture, mix(uvD.xy, uvD.zw, v_texCoords));
|
||||
vec4 colorTexE = texture(u_texture, mix(uvE.xy, uvE.zw, v_texCoords));
|
||||
vec4 colorTexF = texture(u_texture, mix(uvF.xy, uvF.zw, v_texCoords));
|
||||
vec4 colorTexG = texture(u_texture, mix(uvG.xy, uvG.zw, v_texCoords));
|
||||
vec4 colorTexH = texture(u_texture, mix(uvH.xy, uvH.zw, v_texCoords));
|
||||
|
||||
|
||||
vec2 astrumTexCoord = (v_texCoords * drawOffsetSize.zw + drawOffsetSize.xy + astrumScroll) / tex1Size;
|
||||
vec4 randomness = snoise4((gl_FragCoord.xy - astrumScroll) * 0.16) * 2.0; // multiply by 2 so that the "density" of the stars would be same as the non-random version
|
||||
|
||||
|
||||
vec4 colorTex0 = texture(u_texture, skyboxTexCoord);
|
||||
vec4 colorTex1 = texture(tex1, astrumTexCoord) * randomness;
|
||||
|
||||
// notations used: https://en.wikipedia.org/wiki/File:Enclosing_points.svg and https://en.wikipedia.org/wiki/File:3D_interpolation2.svg
|
||||
vec4 colorTex0 = mix(
|
||||
mix(
|
||||
mix(colorTexA, colorTexE, texBlend.z), // c00 = c000..c100
|
||||
mix(colorTexC, colorTexG, texBlend.z), // c10 = c010..c110
|
||||
texBlend.y
|
||||
), // c0 = c00..c10
|
||||
mix(
|
||||
mix(colorTexB, colorTexF, texBlend.z), // c01 = c001..c101
|
||||
mix(colorTexD, colorTexH, texBlend.z), // c11 = c011..c111
|
||||
texBlend.y
|
||||
), // c1 = c01..c11
|
||||
texBlend.x
|
||||
); // c = c0..c1
|
||||
|
||||
|
||||
fragColor = (max(colorTex0, colorTex1) * boolean.yyyx) + boolean.xxxy;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#version 150
|
||||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ PlainText = ? regular string but does not contain { c U r L y } brackets ? ;
|
||||
function ShowMsg(string: String, vararg args: String) { ... } // pre-defined
|
||||
|
||||
val m = "Give {0} {P.0 1} to {2.ACC}"
|
||||
ShowMsg(m, 42, "GAME_ITEM_COAL", conversationTarget.actorValue.name)
|
||||
ShowMsg(m, 42, "ITEM_COAL", conversationTarget.actorValue.name)
|
||||
|
||||
val m2 = "{0}{G.0 을 를} 찾을 수 없습니다"
|
||||
ShowMsg(m2, something)
|
||||
|
||||
BIN
work_files/graphics/sprites/fixtures/electronics_workbench.kra
LFS
Normal file
BIN
work_files/graphics/sprites/fixtures/electronics_workbench.kra
LFS
Normal file
Binary file not shown.
Reference in New Issue
Block a user