mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 08:38:30 +09:00
Compare commits
30 Commits
v0.3.3-tes
...
v0.3.3-tes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1e45f1743 | ||
|
|
8dda7ac79b | ||
|
|
74b8cc20b7 | ||
|
|
f75a7dd812 | ||
|
|
b2454e4ca2 | ||
|
|
45af955488 | ||
|
|
1f39b9d448 | ||
|
|
26a4cdbce1 | ||
|
|
bf87dc04cb | ||
|
|
8535b0ce13 | ||
|
|
6e0004f165 | ||
|
|
845333f33d | ||
|
|
6988feb731 | ||
|
|
ac2c7b1148 | ||
|
|
d6145fd0da | ||
|
|
194089827c | ||
|
|
d69d032f74 | ||
|
|
a9dbea3d16 | ||
|
|
52938a4b60 | ||
|
|
a21f986f30 | ||
|
|
547158a313 | ||
|
|
0a8b5f33f4 | ||
|
|
da8d620766 | ||
|
|
7dd520393c | ||
|
|
dc83e12170 | ||
|
|
d6b2940d8f | ||
|
|
c5dfe46b76 | ||
|
|
3d3926c08b | ||
|
|
9a90bf69d4 | ||
|
|
0ed5472d8a |
@@ -5,10 +5,7 @@ import com.badlogic.gdx.Input
|
|||||||
import com.badlogic.gdx.graphics.*
|
import com.badlogic.gdx.graphics.*
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.*
|
||||||
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.langpack.Lang
|
||||||
import net.torvald.terrarum.modulecomputers.gameactors.FixtureHomeComputer
|
import net.torvald.terrarum.modulecomputers.gameactors.FixtureHomeComputer
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
@@ -18,8 +15,8 @@ import net.torvald.tsvm.peripheral.GraphicsAdapter
|
|||||||
import net.torvald.unicode.*
|
import net.torvald.unicode.*
|
||||||
|
|
||||||
internal class UIHomeComputer : UICanvas(
|
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
|
toggleKeyLiteral = null,
|
||||||
toggleButtonLiteral = App.getConfigInt("control_gamepad_start"),
|
toggleButtonLiteral = "control_gamepad_start",
|
||||||
) {
|
) {
|
||||||
override var width = 640
|
override var width = 640
|
||||||
override var height = 480
|
override var height = 480
|
||||||
@@ -45,7 +42,7 @@ internal class UIHomeComputer : UICanvas(
|
|||||||
private val fbo = FrameBuffer(Pixmap.Format.RGBA8888, width, height, false)
|
private val fbo = FrameBuffer(Pixmap.Format.RGBA8888, width, height, false)
|
||||||
|
|
||||||
private val controlHelp =
|
private val controlHelp =
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}\u3000 " +
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}\u3000 " +
|
||||||
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_T$KEYCAP_R Terminate\u3000" +
|
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_T$KEYCAP_R Terminate\u3000" +
|
||||||
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_R$KEYCAP_S Reset\u3000" +
|
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_R$KEYCAP_S Reset\u3000" +
|
||||||
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_R$KEYCAP_Q SysRq"
|
"$KEYCAP_CTRL$KEYCAP_SHIFT$KEYCAP_R$KEYCAP_Q SysRq"
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"GAME_ACTION_MOVE_VERB" : "Move",
|
"GAME_ACTION_MOVE_VERB" : "Move",
|
||||||
"GAME_ACTION_ZOOM" : "Zoom",
|
"GAME_ACTION_ZOOM" : "Zoom",
|
||||||
"MENU_IO_AUTOSAVE": "Autosave",
|
"MENU_IO_AUTOSAVE": "Autosave",
|
||||||
|
"MENU_IO_CLEAR": "Clear",
|
||||||
"MENU_IO_IMPORT": "Import",
|
"MENU_IO_IMPORT": "Import",
|
||||||
"MENU_IO_MANUAL_SAVE": "Manual Save",
|
"MENU_IO_MANUAL_SAVE": "Manual Save",
|
||||||
"MENU_LABEL_COPYRIGHT": "Copyright",
|
"MENU_LABEL_COPYRIGHT": "Copyright",
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
"MENU_LABEL_IME": "IME",
|
"MENU_LABEL_IME": "IME",
|
||||||
"MENU_LABEL_IME_TOGGLE": "Toggle IME",
|
"MENU_LABEL_IME_TOGGLE": "Toggle IME",
|
||||||
"MENU_LABEL_KEYBOARD_LAYOUT": "Keyboard Layout",
|
"MENU_LABEL_KEYBOARD_LAYOUT": "Keyboard Layout",
|
||||||
|
"MENU_LABEL_PASTE": "Paste",
|
||||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "Paste from Clipboard",
|
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "Paste from Clipboard",
|
||||||
"MENU_LABEL_PRESS_START_SYMBOL": "Press >",
|
"MENU_LABEL_PRESS_START_SYMBOL": "Press >",
|
||||||
"MENU_LABEL_RESET" : "Reset",
|
"MENU_LABEL_RESET" : "Reset",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"GAME_ACTION_MOVE_VERB" : "이동하기",
|
"GAME_ACTION_MOVE_VERB" : "이동하기",
|
||||||
"GAME_ACTION_ZOOM" : "확대·축소",
|
"GAME_ACTION_ZOOM" : "확대·축소",
|
||||||
"MENU_IO_AUTOSAVE": "자동 저장",
|
"MENU_IO_AUTOSAVE": "자동 저장",
|
||||||
|
"MENU_IO_CLEAR": "지우기",
|
||||||
"MENU_IO_IMPORT": "가져오기",
|
"MENU_IO_IMPORT": "가져오기",
|
||||||
"MENU_IO_MANUAL_SAVE": "수동 저장",
|
"MENU_IO_MANUAL_SAVE": "수동 저장",
|
||||||
"MENU_LABEL_COPYRIGHT": "저작권",
|
"MENU_LABEL_COPYRIGHT": "저작권",
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
"MENU_LABEL_IME": "입력기",
|
"MENU_LABEL_IME": "입력기",
|
||||||
"MENU_LABEL_IME_TOGGLE": "입력기 켜고 끄기",
|
"MENU_LABEL_IME_TOGGLE": "입력기 켜고 끄기",
|
||||||
"MENU_LABEL_KEYBOARD_LAYOUT": "자판 배열",
|
"MENU_LABEL_KEYBOARD_LAYOUT": "자판 배열",
|
||||||
|
"MENU_LABEL_PASTE": "붙여넣기",
|
||||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "복사한 텍스트 붙여넣기",
|
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "복사한 텍스트 붙여넣기",
|
||||||
"MENU_LABEL_PRESS_START_SYMBOL": ">을 누르세요",
|
"MENU_LABEL_PRESS_START_SYMBOL": ">을 누르세요",
|
||||||
"MENU_LABEL_RESET" : "재설정",
|
"MENU_LABEL_RESET" : "재설정",
|
||||||
|
|||||||
@@ -32,4 +32,5 @@ Teleport
|
|||||||
ToggleNoClip
|
ToggleNoClip
|
||||||
Zoom
|
Zoom
|
||||||
DynToStatic
|
DynToStatic
|
||||||
DebugFillInventory
|
DebugFillInventory
|
||||||
|
Uuid
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "This is a world currently playing."
|
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "This is a world currently playing.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_1": "Copy the Avatar Code into the clipboard, then hit the Paste button below.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_2": ""
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "현재 플레이 중인 월드입니다."
|
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "현재 플레이 중인 월드입니다.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_1": "아바타 코드를 클립보드에 복사한 다음, 아래의 붙여넣기 버튼을 눌러주세요.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_2": ""
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,21 @@
|
|||||||
"skyboxGradColourMap": "generic_skybox.tga",
|
"skyboxGradColourMap": "generic_skybox.tga",
|
||||||
"daylightClut": "clut_daylight.tga",
|
"daylightClut": "clut_daylight.tga",
|
||||||
"classification": "generic",
|
"classification": "generic",
|
||||||
"extraImages": [
|
"cloudChance": 250,
|
||||||
|
"cloudGamma": [0.48, 1.8],
|
||||||
]
|
"cloudGammaVariance": [0.1, 0.1],
|
||||||
|
"windSpeed": 10.25,
|
||||||
|
"windSpeedVariance": 1.0,
|
||||||
|
"clouds": {
|
||||||
|
"cumulonimbus": {
|
||||||
|
"filename": "cloud_large.png", "tw": 2048, "th": 1024, "probability": 0.2,
|
||||||
|
"baseScale": 2.0, "scaleVariance": 0.3333333,
|
||||||
|
"altLow": 80, "altHigh": 120
|
||||||
|
},
|
||||||
|
"cumulus": {
|
||||||
|
"filename": "cloud_normal.png", "tw": 1024, "th": 512, "probability": 1.0,
|
||||||
|
"baseScale": 1.0, "scaleVariance": 0.6,
|
||||||
|
"altLow": 80, "altHigh": 800
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"globalLight": "generic_light.tga",
|
|
||||||
"skyboxGradColourMap": "generic_skybox.tga",
|
|
||||||
"classification": "genericrain",
|
|
||||||
"extraImages": [
|
|
||||||
"raindrop.tga"
|
|
||||||
],
|
|
||||||
"mixFrom": "__CURRENTWEATHER",
|
|
||||||
"mixPercentage": 80.0
|
|
||||||
}
|
|
||||||
27
assets/mods/basegame/weathers/WeatherOvercast.json
Normal file
27
assets/mods/basegame/weathers/WeatherOvercast.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"skyboxGradColourMap": "generic_skybox.tga",
|
||||||
|
"daylightClut": "clut_daylight.tga",
|
||||||
|
"classification": "overcast",
|
||||||
|
"cloudChance": 300,
|
||||||
|
"cloudGamma": [2.2, 2.0],
|
||||||
|
"cloudGammaVariance": [0.1, 0.1],
|
||||||
|
"windSpeed": 10.45,
|
||||||
|
"windSpeedVariance": 1.0,
|
||||||
|
"clouds": {
|
||||||
|
"cumulus": {
|
||||||
|
"filename": "cloud_normal.png", "tw": 1024, "th": 512, "probability": 0.1,
|
||||||
|
"baseScale": 0.8, "scaleVariance": 0.6,
|
||||||
|
"altLow": 80, "altHigh": 800
|
||||||
|
},
|
||||||
|
"cumulonimbus": {
|
||||||
|
"filename": "cloud_large.png", "tw": 2048, "th": 1024, "probability": 0.4,
|
||||||
|
"baseScale": 2.0, "scaleVariance": 0.3333333,
|
||||||
|
"altLow": 90, "altHigh": 120
|
||||||
|
},
|
||||||
|
"nimbostratus": {
|
||||||
|
"filename": "cloud_wide.png", "tw": 4096, "th": 1024, "probability": 1.0,
|
||||||
|
"baseScale": 4.0, "scaleVariance": 0.1,
|
||||||
|
"altLow": 100, "altHigh": 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/mods/basegame/weathers/cloud_large.kra
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_large.kra
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/weathers/cloud_large.png
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_large.png
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/weathers/cloud_normal.kra
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_normal.kra
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/weathers/cloud_normal.png
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_normal.png
LFS
Normal file
Binary file not shown.
26
assets/mods/basegame/weathers/cloud_texture_instruction.md
Normal file
26
assets/mods/basegame/weathers/cloud_texture_instruction.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
## actually blending
|
||||||
|
1. On Krita, load the cloudmap
|
||||||
|
2. Select and isolate suitable piece of the cloud
|
||||||
|
3. With liquefying brush, make the bottom flat
|
||||||
|
4. On new tab, load the solidmap
|
||||||
|
5. Resize the solidmap to 1024x1024
|
||||||
|
6. Rotate the solidmap by 30 deg or so
|
||||||
|
7. Overlay the processed solidmap to the cloudmap, opacity=30%
|
||||||
|
8. With airbrush tool, manually add the shade (see cloud_normal.kra to get the gist of it)
|
||||||
|
|
||||||
|
### cloudmap
|
||||||
|
1. On GIMP, prepare 4096x4096 canvas
|
||||||
|
2. Create Simplex Noise with following parameters:
|
||||||
|
- Scale: arbitrary (0.05 - 0.2)
|
||||||
|
- Iterations: MAX
|
||||||
|
- Seed: anything but 0
|
||||||
|
|
||||||
|
### solidmap
|
||||||
|
1. On GIMP, prepare 4096x4096 canvas
|
||||||
|
2. Create Solid Noise with following parameters:
|
||||||
|
- XY Size: 16.0
|
||||||
|
- Detail: MAX
|
||||||
|
- Tileable: check
|
||||||
|
- Turbulent: check
|
||||||
|
- Seed: anything but 0
|
||||||
|
|
||||||
BIN
assets/mods/basegame/weathers/cloud_wide.kra
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_wide.kra
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/weathers/cloud_wide.png
LFS
Normal file
BIN
assets/mods/basegame/weathers/cloud_wide.png
LFS
Normal file
Binary file not shown.
@@ -35,6 +35,7 @@ mv $DESTDIR/assets_release $DESTDIR/assets
|
|||||||
cp "../out/TerrarumBuild.jar" $DESTDIR/out/
|
cp "../out/TerrarumBuild.jar" $DESTDIR/out/
|
||||||
|
|
||||||
# Temporary solution: zip everything
|
# Temporary solution: zip everything
|
||||||
|
rm "out/TerrarumWindows.x86.zip"
|
||||||
zip -r -9 -l "out/TerrarumWindows.x86.zip" $DESTDIR
|
zip -r -9 -l "out/TerrarumWindows.x86.zip" $DESTDIR
|
||||||
rm -rf $DESTDIR || true
|
rm -rf $DESTDIR || true
|
||||||
echo "Build successful: $DESTDIR"
|
echo "Build successful: $DESTDIR"
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ rm $DESTDIR/graphics/*.bat
|
|||||||
rm $DESTDIR/keylayout/*.not_ime
|
rm $DESTDIR/keylayout/*.not_ime
|
||||||
rm $DESTDIR/mods/basegame/blocks/*.gz
|
rm $DESTDIR/mods/basegame/blocks/*.gz
|
||||||
rm $DESTDIR/mods/basegame/blocks/*.txt
|
rm $DESTDIR/mods/basegame/blocks/*.txt
|
||||||
|
rm $DESTDIR/mods/basegame/weathers/*.txt
|
||||||
|
rm $DESTDIR/mods/basegame/weathers/*.md
|
||||||
|
rm $DESTDIR/mods/basegame/weathers/*.kra
|
||||||
rm -r $DESTDIR/mods/basegame/sounds
|
rm -r $DESTDIR/mods/basegame/sounds
|
||||||
rm -r $DESTDIR/mods/dwarventech
|
rm -r $DESTDIR/mods/dwarventech
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
#include <windows.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <tchar.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
return system(".\\out\\runtime-windows-x86\\bin\\Terrarum.exe -jar .\\out\\TerrarumBuild.jar");
|
|
||||||
|
ShellExecute(NULL, "open", "\".\\out\\runtime-windows-x86\\bin\\Terrarum.exe\"", "-jar \".\\out\\TerrarumBuild.jar\"", NULL, SW_HIDE);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
//return system(".\\out\\runtime-windows-x86\\bin\\Terrarum.exe -jar .\\out\\TerrarumBuild.jar");
|
||||||
}
|
}
|
||||||
@@ -248,6 +248,10 @@ final public class FastMath {
|
|||||||
return interpolateCatmullRom(u, 0.5f, p0, p1, p2, p3);
|
return interpolateCatmullRom(u, 0.5f, p0, p1, p2, p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float interpolateCatmullRom(float u, float[] ps) {
|
||||||
|
return interpolateCatmullRom(u, 0.5f, ps[0], ps[1], ps[2], ps[3]);
|
||||||
|
}
|
||||||
|
|
||||||
/**Interpolate a spline between at least 4 control points following the Catmull-Rom equation.
|
/**Interpolate a spline between at least 4 control points following the Catmull-Rom equation.
|
||||||
* here is the interpolation matrix
|
* here is the interpolation matrix
|
||||||
* m = [ 0.0 1.0 0.0 0.0 ]
|
* m = [ 0.0 1.0 0.0 0.0 ]
|
||||||
@@ -331,8 +335,7 @@ final public class FastMath {
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*public static float interpolateHermite(float scale, float p0, float p1, float p2, float p3) {
|
||||||
public static float interpolateHermite(float scale, float p0, float p1, float p2, float p3) {
|
|
||||||
// return interpolateHermite(scale, p0, p1, p2, p3, 0f, 0f);
|
// return interpolateHermite(scale, p0, p1, p2, p3, 0f, 0f);
|
||||||
float mu2 = scale * scale;
|
float mu2 = scale * scale;
|
||||||
float mu3 = mu2 * scale;
|
float mu3 = mu2 * scale;
|
||||||
@@ -350,7 +353,7 @@ final public class FastMath {
|
|||||||
float a3 = -2*mu3 + 3*mu2 + 0;
|
float a3 = -2*mu3 + 3*mu2 + 0;
|
||||||
|
|
||||||
return a0*p1 + a1*m0 + a2*m1 + a3*p2;
|
return a0*p1 + a1*m0 + a2*m1 + a3*p2;
|
||||||
}
|
}*/
|
||||||
//public static float interpolateHermite(float scale, float p0, float p1, float p2, float p3, float tension, float bias) {}
|
//public static float interpolateHermite(float scale, float p0, float p1, float p2, float p3, float tension, float bias) {}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -269,8 +269,8 @@ public class App implements ApplicationListener {
|
|||||||
Gdx.gl20.glViewport(0, 0, width, height);
|
Gdx.gl20.glViewport(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int TICKS = 64;
|
public static final int TICK_SPEED = 64;
|
||||||
public static final float UPDATE_RATE = 1f / TICKS; // apparent framerate will be limited by update rate
|
public static final float UPDATE_RATE = 1f / TICK_SPEED; // apparent framerate will be limited by update rate
|
||||||
|
|
||||||
private static float loadTimer = 0f;
|
private static float loadTimer = 0f;
|
||||||
private static final float showupTime = 100f / 1000f;
|
private static final float showupTime = 100f / 1000f;
|
||||||
@@ -1378,6 +1378,8 @@ public class App implements ApplicationListener {
|
|||||||
* @throws NullPointerException if the specified config simply does not exist.
|
* @throws NullPointerException if the specified config simply does not exist.
|
||||||
*/
|
*/
|
||||||
public static int getConfigInt(String key) {
|
public static int getConfigInt(String key) {
|
||||||
|
if (key == null) return -1;
|
||||||
|
|
||||||
Object cfg = getConfigMaster(key);
|
Object cfg = getConfigMaster(key);
|
||||||
|
|
||||||
if (cfg instanceof Integer) return ((int) cfg);
|
if (cfg instanceof Integer) return ((int) cfg);
|
||||||
|
|||||||
90
src/net/torvald/terrarum/ControlPresets.kt
Normal file
90
src/net/torvald/terrarum/ControlPresets.kt
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Input
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-24.
|
||||||
|
*/
|
||||||
|
object ControlPresets {
|
||||||
|
|
||||||
|
val wasd = hashMapOf<String, Int>(
|
||||||
|
"control_key_up" to Input.Keys.W,
|
||||||
|
"control_key_left" to Input.Keys.A,
|
||||||
|
"control_key_down" to Input.Keys.S,
|
||||||
|
"control_key_right" to Input.Keys.D,
|
||||||
|
|
||||||
|
"control_key_jump" to Input.Keys.SPACE,
|
||||||
|
"control_key_movementaux" to Input.Keys.SHIFT_LEFT, // movement-auxiliary, or hookshot
|
||||||
|
"control_key_inventory" to Input.Keys.Q,
|
||||||
|
"control_key_interact" to Input.Keys.R,
|
||||||
|
"control_key_discard" to Input.Keys.F,
|
||||||
|
"control_key_close" to Input.Keys.X, // this or hard-coded ESC
|
||||||
|
"control_key_zoom" to Input.Keys.Z,
|
||||||
|
|
||||||
|
"control_key_gamemenu" to Input.Keys.TAB,
|
||||||
|
"control_key_crafting" to Input.Keys.E,
|
||||||
|
"control_key_quicksel" to Input.Keys.CONTROL_LEFT, // pie menu is now LShift because CapsLock is actually used by the my bespoke keyboard input
|
||||||
|
)
|
||||||
|
|
||||||
|
val esdf = hashMapOf<String, Int>(
|
||||||
|
"control_key_up" to Input.Keys.E,
|
||||||
|
"control_key_left" to Input.Keys.S,
|
||||||
|
"control_key_down" to Input.Keys.D,
|
||||||
|
"control_key_right" to Input.Keys.F, // ESDF Masterrace
|
||||||
|
|
||||||
|
"control_key_jump" to Input.Keys.SPACE,
|
||||||
|
"control_key_movementaux" to Input.Keys.A, // movement-auxiliary, or hookshot
|
||||||
|
"control_key_inventory" to Input.Keys.Q,
|
||||||
|
"control_key_interact" to Input.Keys.R,
|
||||||
|
"control_key_discard" to Input.Keys.T,
|
||||||
|
"control_key_close" to Input.Keys.C, // this or hard-coded ESC
|
||||||
|
"control_key_zoom" to Input.Keys.Z,
|
||||||
|
|
||||||
|
"control_key_gamemenu" to Input.Keys.TAB,
|
||||||
|
"control_key_crafting" to Input.Keys.W,
|
||||||
|
"control_key_quicksel" to Input.Keys.SHIFT_LEFT, // pie menu is now LShift because CapsLock is actually used by the my bespoke keyboard input
|
||||||
|
)
|
||||||
|
|
||||||
|
val ijkl = hashMapOf<String, Int>(
|
||||||
|
"control_key_up" to Input.Keys.I,
|
||||||
|
"control_key_left" to Input.Keys.J,
|
||||||
|
"control_key_down" to Input.Keys.K,
|
||||||
|
"control_key_right" to Input.Keys.L,
|
||||||
|
|
||||||
|
"control_key_jump" to Input.Keys.SPACE,
|
||||||
|
"control_key_movementaux" to Input.Keys.SEMICOLON, // movement-auxiliary, or hookshot
|
||||||
|
"control_key_inventory" to Input.Keys.P,
|
||||||
|
"control_key_interact" to Input.Keys.U,
|
||||||
|
"control_key_discard" to Input.Keys.Y,
|
||||||
|
"control_key_close" to Input.Keys.M, // this or hard-coded ESC
|
||||||
|
"control_key_zoom" to Input.Keys.SLASH,
|
||||||
|
|
||||||
|
"control_key_gamemenu" to Input.Keys.LEFT_BRACKET,
|
||||||
|
"control_key_crafting" to Input.Keys.O,
|
||||||
|
"control_key_quicksel" to Input.Keys.APOSTROPHE, // pie menu is now LShift because CapsLock is actually used by the my bespoke keyboard input
|
||||||
|
)
|
||||||
|
|
||||||
|
val empty = hashMapOf<String, Int>()
|
||||||
|
|
||||||
|
val presets = hashMapOf( // unordered
|
||||||
|
"WASD" to wasd,
|
||||||
|
"ESDF" to esdf,
|
||||||
|
"IJKL" to ijkl,
|
||||||
|
"Custom" to empty,
|
||||||
|
)
|
||||||
|
|
||||||
|
val presetLabels = listOf( // ordered
|
||||||
|
"WASD",
|
||||||
|
"ESDF",
|
||||||
|
"IJKL",
|
||||||
|
"Custom",
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getKey(label: String?): Int {
|
||||||
|
if (label == null) return -1
|
||||||
|
|
||||||
|
val presetName = App.getConfigString("control_preset_keyboard") ?: "Custom"
|
||||||
|
|
||||||
|
return (presets[presetName] ?: throw IllegalStateException("No such keyboard preset: $presetName")).getOrDefault(label, App.getConfigInt(label))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,8 @@ object DefaultConfig {
|
|||||||
|
|
||||||
"usexinput" to true, // when FALSE, LT+RT input on xbox controller is impossible
|
"usexinput" to true, // when FALSE, LT+RT input on xbox controller is impossible
|
||||||
|
|
||||||
|
"control_preset_keyboard" to "WASD",
|
||||||
|
|
||||||
"control_gamepad_keyn" to 3,
|
"control_gamepad_keyn" to 3,
|
||||||
"control_gamepad_keyw" to 2,
|
"control_gamepad_keyw" to 2,
|
||||||
"control_gamepad_keys" to 0,
|
"control_gamepad_keys" to 0,
|
||||||
|
|||||||
@@ -531,6 +531,9 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
else
|
else
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onConfigChange() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun Lock.lock(body: () -> Unit) {
|
inline fun Lock.lock(body: () -> Unit) {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ basegame
|
|||||||
// Commit counts up to the Release 0.3.1: 2278
|
// Commit counts up to the Release 0.3.1: 2278
|
||||||
// Commit counts up to the Release 0.3.2: 2732
|
// Commit counts up to the Release 0.3.2: 2732
|
||||||
|
|
||||||
const val VERSION_TAG: String = "test001"
|
const val VERSION_TAG: String = "test002"
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
// CONFIGURATION FOR TILE MAKER //
|
// CONFIGURATION FOR TILE MAKER //
|
||||||
|
|||||||
@@ -688,7 +688,7 @@ open class ActorWithBody : Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun displaceHitbox() {
|
private fun displaceHitbox() {
|
||||||
val printdbg1 = true && App.IS_DEVELOPMENT_BUILD
|
val printdbg1 = false && App.IS_DEVELOPMENT_BUILD
|
||||||
// // HOW IT SHOULD WORK // //
|
// // HOW IT SHOULD WORK // //
|
||||||
// ////////////////////////
|
// ////////////////////////
|
||||||
// combineVeloToMoveDelta now
|
// combineVeloToMoveDelta now
|
||||||
|
|||||||
@@ -5,14 +5,11 @@ import com.badlogic.gdx.Input
|
|||||||
import com.badlogic.gdx.InputAdapter
|
import com.badlogic.gdx.InputAdapter
|
||||||
import com.badlogic.gdx.controllers.Controllers
|
import com.badlogic.gdx.controllers.Controllers
|
||||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.App.printdbgerr
|
import net.torvald.terrarum.App.printdbgerr
|
||||||
import net.torvald.terrarum.ItemCodex
|
|
||||||
import net.torvald.terrarum.Terrarum
|
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
import net.torvald.terrarum.controller.TerrarumController
|
import net.torvald.terrarum.controller.TerrarumController
|
||||||
import net.torvald.terrarum.floorToInt
|
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
import net.torvald.terrarum.gameitems.GameItem
|
import net.torvald.terrarum.gameitems.GameItem
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
@@ -168,7 +165,7 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
|
|||||||
|
|
||||||
// pie menu
|
// pie menu
|
||||||
if (App.getConfigIntArray("control_key_quickselalt").contains(keycode)
|
if (App.getConfigIntArray("control_key_quickselalt").contains(keycode)
|
||||||
|| keycode == App.getConfigInt("control_key_quicksel")) {
|
|| keycode == ControlPresets.getKey("control_key_quicksel")) {
|
||||||
terrarumIngame.uiPieMenu.setAsOpen()
|
terrarumIngame.uiPieMenu.setAsOpen()
|
||||||
terrarumIngame.uiQuickBar.setAsClose()
|
terrarumIngame.uiQuickBar.setAsClose()
|
||||||
}
|
}
|
||||||
@@ -194,7 +191,7 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
|
|||||||
|
|
||||||
private fun tKeyUp(keycode: Int): Boolean {
|
private fun tKeyUp(keycode: Int): Boolean {
|
||||||
if (App.getConfigIntArray("control_key_quickselalt").contains(keycode)
|
if (App.getConfigIntArray("control_key_quickselalt").contains(keycode)
|
||||||
|| keycode == App.getConfigInt("control_key_quicksel")) {
|
|| keycode == ControlPresets.getKey("control_key_quicksel")) {
|
||||||
terrarumIngame.uiPieMenu.setAsClose()
|
terrarumIngame.uiPieMenu.setAsClose()
|
||||||
terrarumIngame.uiQuickBar.setAsOpen()
|
terrarumIngame.uiQuickBar.setAsOpen()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
|
|
||||||
IngameRenderer.setRenderedWorld(gameWorld)
|
IngameRenderer.setRenderedWorld(gameWorld)
|
||||||
|
WeatherMixer.internalReset()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
|
|||||||
@@ -255,7 +255,9 @@ object IngameRenderer : Disposable {
|
|||||||
gdxClearAndEnableBlend(0f, 0f, 0f, 0f)
|
gdxClearAndEnableBlend(0f, 0f, 0f, 0f)
|
||||||
|
|
||||||
// draw sky
|
// draw sky
|
||||||
WeatherMixer.render(camera, batch, world)
|
measureDebugTime("WeatherMixer.render") {
|
||||||
|
WeatherMixer.render(camera, batch, world)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// normal behaviour
|
// normal behaviour
|
||||||
|
|||||||
@@ -166,12 +166,12 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
||||||
val world = ReadSimpleWorld(reader, file)
|
val world = ReadSimpleWorld(reader, file)
|
||||||
demoWorld = world
|
demoWorld = world
|
||||||
demoWorld.worldTime.timeDelta = 330 // a year = 8 minutes
|
demoWorld.worldTime.timeDelta = 30
|
||||||
printdbg(this, "Demo world loaded")
|
printdbg(this, "Demo world loaded")
|
||||||
}
|
}
|
||||||
catch (e: IOException) {
|
catch (e: IOException) {
|
||||||
demoWorld = GameWorld(LandUtil.CHUNK_W, LandUtil.CHUNK_H, 0L, 0L)
|
demoWorld = GameWorld(LandUtil.CHUNK_W, LandUtil.CHUNK_H, 0L, 0L)
|
||||||
demoWorld.worldTime.timeDelta = 60
|
demoWorld.worldTime.timeDelta = 30
|
||||||
printdbg(this, "Demo world not found, using empty world")
|
printdbg(this, "Demo world not found, using empty world")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,6 +210,8 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
|
|
||||||
IngameRenderer.setRenderedWorld(demoWorld)
|
IngameRenderer.setRenderedWorld(demoWorld)
|
||||||
|
WeatherMixer.internalReset()
|
||||||
|
WeatherMixer.titleScreenInitWeather()
|
||||||
|
|
||||||
|
|
||||||
// load a half-gradient texture that would be used throughout the titlescreen and its sub UIs
|
// load a half-gradient texture that would be used throughout the titlescreen and its sub UIs
|
||||||
@@ -285,20 +287,15 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val updateScreen = { delta: Float ->
|
private val updateScreen = { delta: Float ->
|
||||||
// TODO: desynched weather and time-of-day change
|
|
||||||
|
|
||||||
val forcedTime = 32880 // 9h08m
|
|
||||||
demoWorld.globalLight = WeatherMixer.globalLightNow
|
demoWorld.globalLight = WeatherMixer.globalLightNow
|
||||||
// demoWorld.globalLight = WeatherMixer.getGlobalLightOfTimeOfNoon()
|
|
||||||
demoWorld.updateWorldTime(delta)
|
demoWorld.updateWorldTime(delta)
|
||||||
// WeatherMixer.update(delta, cameraPlayer, demoWorld)
|
WeatherMixer.update(delta, cameraPlayer, demoWorld)
|
||||||
WeatherMixer.forceTimeAt = forcedTime
|
|
||||||
cameraPlayer.update(delta)
|
cameraPlayer.update(delta)
|
||||||
|
|
||||||
// worldcamera update AFTER cameraplayer in this case; the other way is just an exception for actual ingame SFX
|
// worldcamera update AFTER cameraplayer in this case; the other way is just an exception for actual ingame SFX
|
||||||
WorldCamera.update(demoWorld, cameraPlayer)
|
WorldCamera.update(demoWorld, cameraPlayer)
|
||||||
|
|
||||||
|
|
||||||
// update UIs //
|
// update UIs //
|
||||||
uiContainer.forEach { it?.update(delta) }
|
uiContainer.forEach { it?.update(delta) }
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/net/torvald/terrarum/modulebasegame/console/Uuid.kt
Normal file
22
src/net/torvald/terrarum/modulebasegame/console/Uuid.kt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.console
|
||||||
|
|
||||||
|
import net.torvald.terrarum.INGAME
|
||||||
|
import net.torvald.terrarum.ccG
|
||||||
|
import net.torvald.terrarum.ccY
|
||||||
|
import net.torvald.terrarum.console.ConsoleCommand
|
||||||
|
import net.torvald.terrarum.console.Echo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-22.
|
||||||
|
*/
|
||||||
|
object Uuid : ConsoleCommand {
|
||||||
|
override fun execute(args: Array<String>) {
|
||||||
|
val worldUUID = INGAME.world.worldIndex
|
||||||
|
val playerUUID = INGAME.actorGamer.uuid
|
||||||
|
Echo("${ccY}World UUID: ${ccG}$worldUUID")
|
||||||
|
Echo("${ccY}Player UUID: ${ccG}$playerUUID")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun printUsage() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -254,11 +254,11 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
|
|
||||||
private fun updateGamerControlBox() {
|
private fun updateGamerControlBox() {
|
||||||
if (isGamer) {
|
if (isGamer) {
|
||||||
isUpDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_up"))
|
isUpDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_up"))
|
||||||
isLeftDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_left"))
|
isLeftDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_left"))
|
||||||
isDownDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_down"))
|
isDownDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_down"))
|
||||||
isRightDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_right"))
|
isRightDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_right"))
|
||||||
isJumpDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_jump"))
|
isJumpDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_jump"))
|
||||||
|
|
||||||
val gamepad = App.gamepad
|
val gamepad = App.gamepad
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
axisRX = gamepad.getAxis(App.getConfigInt("control_gamepad_axisrx"))
|
axisRX = gamepad.getAxis(App.getConfigInt("control_gamepad_axisrx"))
|
||||||
axisRY = gamepad.getAxis(App.getConfigInt("control_gamepad_axisry"))
|
axisRY = gamepad.getAxis(App.getConfigInt("control_gamepad_axisry"))
|
||||||
|
|
||||||
isJumpDown = Gdx.input.isKeyPressed(App.getConfigInt("control_key_jump")) ||
|
isJumpDown = Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_jump")) ||
|
||||||
gamepad.getButton(App.getConfigInt("control_gamepad_ltrigger"))
|
gamepad.getButton(App.getConfigInt("control_gamepad_ltrigger"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,11 +348,11 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
// ↑F, ↓S
|
// ↑F, ↓S
|
||||||
if (isRightDown && !isLeftDown) {
|
if (isRightDown && !isLeftDown) {
|
||||||
walkHorizontal(false, AXIS_KEYBOARD)
|
walkHorizontal(false, AXIS_KEYBOARD)
|
||||||
prevHMoveKey = App.getConfigInt("control_key_right")
|
prevHMoveKey = ControlPresets.getKey("control_key_right")
|
||||||
} // ↓F, ↑S
|
} // ↓F, ↑S
|
||||||
else if (isLeftDown && !isRightDown) {
|
else if (isLeftDown && !isRightDown) {
|
||||||
walkHorizontal(true, AXIS_KEYBOARD)
|
walkHorizontal(true, AXIS_KEYBOARD)
|
||||||
prevHMoveKey = App.getConfigInt("control_key_left")
|
prevHMoveKey = ControlPresets.getKey("control_key_left")
|
||||||
} // ↓F, ↓S
|
} // ↓F, ↓S
|
||||||
/*else if (isLeftDown && isRightDown) {
|
/*else if (isLeftDown && isRightDown) {
|
||||||
if (prevHMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_LEFT)) {
|
if (prevHMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_LEFT)) {
|
||||||
@@ -376,11 +376,11 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
// ↑E, ↓D
|
// ↑E, ↓D
|
||||||
if (isDownDown && !isUpDown) {
|
if (isDownDown && !isUpDown) {
|
||||||
walkVertical(false, AXIS_KEYBOARD)
|
walkVertical(false, AXIS_KEYBOARD)
|
||||||
prevVMoveKey = App.getConfigInt("control_key_down")
|
prevVMoveKey = ControlPresets.getKey("control_key_down")
|
||||||
} // ↓E, ↑D
|
} // ↓E, ↑D
|
||||||
else if (isUpDown && !isDownDown) {
|
else if (isUpDown && !isDownDown) {
|
||||||
walkVertical(true, AXIS_KEYBOARD)
|
walkVertical(true, AXIS_KEYBOARD)
|
||||||
prevVMoveKey = App.getConfigInt("control_key_up")
|
prevVMoveKey = ControlPresets.getKey("control_key_up")
|
||||||
} // ↓E, ↓D
|
} // ↓E, ↓D
|
||||||
/*else if (isUpDown && isDownDown) {
|
/*else if (isUpDown && isDownDown) {
|
||||||
if (prevVMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_UP)) {
|
if (prevVMoveKey == KeyMap.getKeyCode(EnumKeyFunc.MOVE_UP)) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class UIBasicInfo() : UICanvas() {
|
|||||||
ELuptimer += delta
|
ELuptimer += delta
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouseUp || Gdx.input.isKeyPressed(App.getConfigInt("control_key_interact"))) {
|
if (mouseUp || Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_interact"))) {
|
||||||
ELuptimer = 0f
|
ELuptimer = 0f
|
||||||
ELon = true
|
ELon = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
else
|
else
|
||||||
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}\u3000 " +
|
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}\u3000 " +
|
||||||
"$gamepadLabelLEFTRIGHT ${Lang["GAME_OBJECTIVE_MULTIPLIER"]}\u3000 " +
|
"$gamepadLabelLEFTRIGHT ${Lang["GAME_OBJECTIVE_MULTIPLIER"]}\u3000 " +
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|||||||
import net.torvald.unicode.EMDASH
|
import net.torvald.unicode.EMDASH
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.CommonResourcePool
|
import net.torvald.terrarum.CommonResourcePool
|
||||||
|
import net.torvald.terrarum.ControlPresets
|
||||||
import net.torvald.terrarum.gamecontroller.*
|
import net.torvald.terrarum.gamecontroller.*
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.linearSearch
|
import net.torvald.terrarum.linearSearch
|
||||||
@@ -318,7 +319,7 @@ private class UIItemInputKeycap(
|
|||||||
else if (parent.shiftin && keysymsLow[1]?.isNotEmpty() == true) keysymsLow[1]
|
else if (parent.shiftin && keysymsLow[1]?.isNotEmpty() == true) keysymsLow[1]
|
||||||
else keysymsLow[0]) ?: ""
|
else keysymsLow[0]) ?: ""
|
||||||
|
|
||||||
val keysym0: Array<String?> = if (KeyToggler.isOn(App.getConfigInt("control_key_toggleime"))) {
|
val keysym0: Array<String?> = if (KeyToggler.isOn(ControlPresets.getKey("control_key_toggleime"))) {
|
||||||
if (parent.highlayer == null) arrayOf(keysymLow,keysymLow,keysymLow,keysymLow)
|
if (parent.highlayer == null) arrayOf(keysymLow,keysymLow,keysymLow,keysymLow)
|
||||||
else {
|
else {
|
||||||
val keysyms = parent.highlayer!!.config.symbols
|
val keysyms = parent.highlayer!!.config.symbols
|
||||||
|
|||||||
161
src/net/torvald/terrarum/modulebasegame/ui/UIImportAvatar.kt
Normal file
161
src/net/torvald/terrarum/modulebasegame/ui/UIImportAvatar.kt
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.ui
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.Input
|
||||||
|
import com.badlogic.gdx.graphics.Camera
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.Second
|
||||||
|
import net.torvald.terrarum.ceilToInt
|
||||||
|
import net.torvald.terrarum.gamecontroller.*
|
||||||
|
import net.torvald.terrarum.langpack.Lang
|
||||||
|
import net.torvald.terrarum.serialise.Ascii85Codec
|
||||||
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
import net.torvald.terrarum.ui.UIItem
|
||||||
|
import net.torvald.terrarum.ui.UIItemTextButton
|
||||||
|
import net.torvald.terrarum.utils.Clipboard
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-24.
|
||||||
|
*/
|
||||||
|
class UIImportAvatar(val remoCon: UIRemoCon) : Advanceable() {
|
||||||
|
|
||||||
|
override var width = 480 // SAVE_CELL_WIDTH
|
||||||
|
override var height = 480
|
||||||
|
override var openCloseTime: Second = OPENCLOSE_GENERIC
|
||||||
|
|
||||||
|
private val drawX = (Toolkit.drawWidth - width) / 2
|
||||||
|
private val drawY = (App.scr.height - height) / 2
|
||||||
|
private val cols = 80
|
||||||
|
private val rows = 30
|
||||||
|
private val goButtonWidth = 180
|
||||||
|
|
||||||
|
|
||||||
|
private val codeBox = UIItemCodeBox(this, (Toolkit.drawWidth - App.fontSmallNumbers.W * cols) / 2, drawY, cols, rows)
|
||||||
|
|
||||||
|
private val clearButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_IO_CLEAR"] }, drawX + (width/2 - goButtonWidth) / 2, drawY + height - 24 - 34, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
private val pasteButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_LABEL_PASTE"] }, drawX + width/2 + (width/2 - goButtonWidth) / 2, drawY + height - 24 - 34, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
|
||||||
|
|
||||||
|
private val backButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_LABEL_BACK"] }, drawX + (width/2 - goButtonWidth) / 2, drawY + height - 24, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
private val goButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_IO_IMPORT"] }, drawX + width/2 + (width/2 - goButtonWidth) / 2, drawY + height - 24, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addUIitem(codeBox)
|
||||||
|
addUIitem(clearButton)
|
||||||
|
addUIitem(pasteButton)
|
||||||
|
addUIitem(backButton)
|
||||||
|
addUIitem(goButton)
|
||||||
|
|
||||||
|
clearButton.clickOnceListener = { _,_ ->
|
||||||
|
codeBox.clearTextBuffer()
|
||||||
|
}
|
||||||
|
pasteButton.clickOnceListener = { _,_ ->
|
||||||
|
codeBox.pasteFromClipboard()
|
||||||
|
}
|
||||||
|
backButton.clickOnceListener = { _,_ ->
|
||||||
|
remoCon.openUI(UILoadSavegame(remoCon))
|
||||||
|
}
|
||||||
|
goButton.clickOnceListener = { _,_ ->
|
||||||
|
doImport()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun updateUI(delta: Float) {
|
||||||
|
uiItems.forEach { it.update(delta) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||||
|
uiItems.forEach { it.render(batch, camera) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun advanceMode(button: UIItem) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doImport() {
|
||||||
|
val rawStr = codeBox.textBuffer.toString()
|
||||||
|
// sanity check
|
||||||
|
|
||||||
|
|
||||||
|
val ascii85codec = Ascii85Codec((33..117).map { it.toChar() }.joinToString(""))
|
||||||
|
val ascii85str = rawStr.substring(2 until rawStr.length - 2).replace("z", "!!!!!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UIItemCodeBox(parent: UIImportAvatar, initialX: Int, initialY: Int, val cols: Int = 80, val rows: Int = 24) : UIItem(parent, initialX, initialY) {
|
||||||
|
|
||||||
|
override val width = App.fontSmallNumbers.W * cols
|
||||||
|
override val height = App.fontSmallNumbers.H * rows
|
||||||
|
override fun dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private var highlightCol: Color = Toolkit.Theme.COL_INACTIVE
|
||||||
|
|
||||||
|
var selected = false
|
||||||
|
|
||||||
|
private var textCursorPosition = 0
|
||||||
|
internal var textBuffer = StringBuilder()
|
||||||
|
|
||||||
|
fun pasteFromClipboard() {
|
||||||
|
textBuffer.clear()
|
||||||
|
Clipboard.fetch().forEach {
|
||||||
|
if (it.code in 33..122) textBuffer.append(it)
|
||||||
|
}
|
||||||
|
textCursorPosition += textBuffer.length
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(delta: Float) {
|
||||||
|
super.update(delta)
|
||||||
|
// if (!selected && mousePushed)
|
||||||
|
// selected = true
|
||||||
|
// else if (selected && mouseDown && !mouseUp)
|
||||||
|
// selected = false
|
||||||
|
|
||||||
|
if (textBuffer.isEmpty() && (Gdx.input.isKeyJustPressed(Input.Keys.V) && (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) || Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT)))) {
|
||||||
|
pasteFromClipboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(batch: SpriteBatch, camera: Camera) {
|
||||||
|
// draw box backgrounds
|
||||||
|
batch.color = UIInventoryFull.CELL_COL
|
||||||
|
Toolkit.fillArea(batch, posX, posY, width, height)
|
||||||
|
|
||||||
|
// draw borders
|
||||||
|
batch.color = if (selected) Toolkit.Theme.COL_SELECTED else if (mouseUp) Toolkit.Theme.COL_MOUSE_UP else Toolkit.Theme.COL_INACTIVE
|
||||||
|
Toolkit.drawBoxBorder(batch, posX - 1, posY - 1, width + 2, height + 2)
|
||||||
|
|
||||||
|
// draw texts
|
||||||
|
if (textBuffer.isEmpty()) {
|
||||||
|
batch.color = Toolkit.Theme.COL_INACTIVE
|
||||||
|
App.fontGame.draw(batch, Lang["CONTEXT_IMPORT_AVATAR_INSTRUCTION_1"], posX + 5, posY)
|
||||||
|
App.fontGame.draw(batch, Lang["CONTEXT_IMPORT_AVATAR_INSTRUCTION_2"], posX + 5f, posY + App.fontGame.lineHeight)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
val scroll = ((textBuffer.length.toDouble() / cols).ceilToInt() - rows).coerceAtLeast(0)
|
||||||
|
for (i in scroll * cols until textBuffer.length) {
|
||||||
|
val c = textBuffer[i]
|
||||||
|
val x = ((i - scroll * cols) % cols) * App.fontSmallNumbers.W.toFloat()
|
||||||
|
val y = ((i - scroll * cols) / cols) * App.fontSmallNumbers.H.toFloat()
|
||||||
|
|
||||||
|
App.fontSmallNumbers.draw(batch, "$c", posX + x, posY + y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearTextBuffer() {
|
||||||
|
textBuffer.clear()
|
||||||
|
textCursorPosition = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package net.torvald.terrarum.modulebasegame.ui
|
|||||||
import com.badlogic.gdx.graphics.Camera
|
import com.badlogic.gdx.graphics.Camera
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.App.*
|
import net.torvald.terrarum.App.*
|
||||||
@@ -19,7 +18,7 @@ import net.torvald.unicode.*
|
|||||||
* Created by minjaesong on 2017-10-21.
|
* Created by minjaesong on 2017-10-21.
|
||||||
*/
|
*/
|
||||||
class UIInventoryFull(
|
class UIInventoryFull(
|
||||||
toggleKeyLiteral: Int? = App.getConfigInt("control_key_inventory"), toggleButtonLiteral: Int? = App.getConfigInt("control_gamepad_start"),
|
toggleKeyLiteral: String? = "control_key_inventory", toggleButtonLiteral: String? = "control_gamepad_start",
|
||||||
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
||||||
customPositioning: Boolean = false, // mainly used by vital meter
|
customPositioning: Boolean = false, // mainly used by vital meter
|
||||||
doNotWarnConstant: Boolean = false
|
doNotWarnConstant: Boolean = false
|
||||||
@@ -162,10 +161,10 @@ class UIInventoryFull(
|
|||||||
private val SP = "\u3000 "
|
private val SP = "\u3000 "
|
||||||
val listControlHelp: String
|
val listControlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||||
"$KEYCAP_LEFT_MOUSE ${Lang["GAME_INVENTORY_USE"]}$SP" +
|
"$KEYCAP_LEFT_MOUSE ${Lang["GAME_INVENTORY_USE"]}$SP" +
|
||||||
"$KEYCAP_1$ENDASH\u2009$KEYCAP_0 ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
|
"$KEYCAP_1$ENDASH\u2009$KEYCAP_0 ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_discard"))} ${Lang["GAME_INVENTORY_DROP"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_discard"))} ${Lang["GAME_INVENTORY_DROP"]}"
|
||||||
else
|
else
|
||||||
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||||
"$gamepadLabelLT ${Lang["CONTEXT_ITEM_MAP"]}$SP" +
|
"$gamepadLabelLT ${Lang["CONTEXT_ITEM_MAP"]}$SP" +
|
||||||
@@ -175,7 +174,7 @@ class UIInventoryFull(
|
|||||||
"$gamepadLabelEast ${Lang["GAME_INVENTORY_DROP"]}"
|
"$gamepadLabelEast ${Lang["GAME_INVENTORY_DROP"]}"
|
||||||
val minimapControlHelp: String
|
val minimapControlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||||
"$KEYCAP_LEFT_MOUSE$KEYCAP_MOVE ${Lang["GAME_ACTION_MOVE_VERB"]}"
|
"$KEYCAP_LEFT_MOUSE$KEYCAP_MOVE ${Lang["GAME_ACTION_MOVE_VERB"]}"
|
||||||
else
|
else
|
||||||
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||||
@@ -183,7 +182,7 @@ class UIInventoryFull(
|
|||||||
"$gamepadLabelRT ${Lang["GAME_INVENTORY"]}"
|
"$gamepadLabelRT ${Lang["GAME_INVENTORY"]}"
|
||||||
val gameMenuControlHelp: String
|
val gameMenuControlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
else
|
else
|
||||||
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}$SP" +
|
||||||
"$gamepadLabelLT ${Lang["GAME_INVENTORY"]}"
|
"$gamepadLabelLT ${Lang["GAME_INVENTORY"]}"
|
||||||
@@ -249,7 +248,7 @@ class UIInventoryFull(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allow "control_key_gamemenu" to open this UI and bring system menu immediately
|
// allow "control_key_gamemenu" to open this UI and bring system menu immediately
|
||||||
this.handler.toggleKeyExtra.add { App.getConfigInt("control_key_gamemenu") }
|
this.handler.toggleKeyExtra.add("control_key_gamemenu" )
|
||||||
this.handler.toggleKeyExtraAction.add {
|
this.handler.toggleKeyExtraAction.add {
|
||||||
if (it.isClosed) {
|
if (it.isClosed) {
|
||||||
INGAME.setTooltipMessage(null)
|
INGAME.setTooltipMessage(null)
|
||||||
@@ -263,7 +262,7 @@ class UIInventoryFull(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allow "control_key_crafting" to open this UI and bring system menu immediately
|
// allow "control_key_crafting" to open this UI and bring system menu immediately
|
||||||
this.handler.toggleKeyExtra.add { App.getConfigInt("control_key_crafting") }
|
this.handler.toggleKeyExtra.add("control_key_crafting")
|
||||||
this.handler.toggleKeyExtraAction.add {
|
this.handler.toggleKeyExtraAction.add {
|
||||||
if (it.isClosed) {
|
if (it.isClosed) {
|
||||||
INGAME.setTooltipMessage(null)
|
INGAME.setTooltipMessage(null)
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import com.badlogic.gdx.graphics.Camera
|
|||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.CommonResourcePool
|
|
||||||
import net.torvald.terrarum.DefaultConfig
|
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.ui.*
|
import net.torvald.terrarum.ui.*
|
||||||
|
|
||||||
@@ -37,16 +35,16 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
|
|
||||||
private val keycaps = hashMapOf(
|
private val keycaps = hashMapOf(
|
||||||
Input.Keys.GRAVE to UIItemKeycap(this, 1, 1, null, oneu, ""),
|
Input.Keys.GRAVE to UIItemKeycap(this, 1, 1, null, oneu, ""),
|
||||||
Input.Keys.NUM_1 to UIItemKeycap(this, 33,1, Input.Keys.NUM_1, oneu, "1,3"),
|
Input.Keys.NUM_1 to UIItemKeycap(this, 33,1, null, oneu, "1,3"),
|
||||||
Input.Keys.NUM_2 to UIItemKeycap(this, 65,1, Input.Keys.NUM_2, oneu, "2,3"),
|
Input.Keys.NUM_2 to UIItemKeycap(this, 65,1, null, oneu, "2,3"),
|
||||||
Input.Keys.NUM_3 to UIItemKeycap(this, 97,1, Input.Keys.NUM_3, oneu, "3,3"),
|
Input.Keys.NUM_3 to UIItemKeycap(this, 97,1, null, oneu, "3,3"),
|
||||||
Input.Keys.NUM_4 to UIItemKeycap(this, 129,1, Input.Keys.NUM_4, oneu, "4,3"),
|
Input.Keys.NUM_4 to UIItemKeycap(this, 129,1, null, oneu, "4,3"),
|
||||||
Input.Keys.NUM_5 to UIItemKeycap(this, 161,1, Input.Keys.NUM_5, oneu, "5,3"),
|
Input.Keys.NUM_5 to UIItemKeycap(this, 161,1, null, oneu, "5,3"),
|
||||||
Input.Keys.NUM_6 to UIItemKeycap(this, 193,1, Input.Keys.NUM_6, oneu, "6,3"),
|
Input.Keys.NUM_6 to UIItemKeycap(this, 193,1, null, oneu, "6,3"),
|
||||||
Input.Keys.NUM_7 to UIItemKeycap(this, 225,1, Input.Keys.NUM_7, oneu, "7,3"),
|
Input.Keys.NUM_7 to UIItemKeycap(this, 225,1, null, oneu, "7,3"),
|
||||||
Input.Keys.NUM_8 to UIItemKeycap(this, 257,1, Input.Keys.NUM_8, oneu, "8,3"),
|
Input.Keys.NUM_8 to UIItemKeycap(this, 257,1, null, oneu, "8,3"),
|
||||||
Input.Keys.NUM_9 to UIItemKeycap(this, 289,1, Input.Keys.NUM_9, oneu, "9,3"),
|
Input.Keys.NUM_9 to UIItemKeycap(this, 289,1, null, oneu, "9,3"),
|
||||||
Input.Keys.NUM_0 to UIItemKeycap(this, 321,1, Input.Keys.NUM_0, oneu, "0,3"),
|
Input.Keys.NUM_0 to UIItemKeycap(this, 321,1, null, oneu, "0,3"),
|
||||||
Input.Keys.MINUS to UIItemKeycap(this, 353,1, Input.Keys.MINUS, oneu, "10,3"),
|
Input.Keys.MINUS to UIItemKeycap(this, 353,1, Input.Keys.MINUS, oneu, "10,3"),
|
||||||
Input.Keys.EQUALS to UIItemKeycap(this, 385,1, Input.Keys.EQUALS, oneu, "11,3"),
|
Input.Keys.EQUALS to UIItemKeycap(this, 385,1, Input.Keys.EQUALS, oneu, "11,3"),
|
||||||
Input.Keys.BACKSPACE to UIItemKeycap(this, 417,1, Input.Keys.BACKSPACE, 60, "24,5"),
|
Input.Keys.BACKSPACE to UIItemKeycap(this, 417,1, Input.Keys.BACKSPACE, 60, "24,5"),
|
||||||
@@ -105,25 +103,39 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
) // end of keycaps
|
) // end of keycaps
|
||||||
|
|
||||||
private val resetButtonWidth = 140
|
private val resetButtonWidth = 140
|
||||||
private val buttonReset = UIItemTextButton(this,
|
private val presetButtonWidth = 200
|
||||||
|
/*private val buttonReset = UIItemTextButton(this,
|
||||||
{ Lang["MENU_LABEL_RESET"] },
|
{ Lang["MENU_LABEL_RESET"] },
|
||||||
kbx + (width - resetButtonWidth) / 2,
|
kbx + (width - resetButtonWidth) / 2,
|
||||||
kby + 162 + 12,
|
kby + 162 + 16,
|
||||||
resetButtonWidth,
|
resetButtonWidth,
|
||||||
hasBorder = true,
|
hasBorder = true,
|
||||||
alignment = UIItemTextButton.Companion.Alignment.CENTRE
|
alignment = UIItemTextButton.Companion.Alignment.CENTRE
|
||||||
|
)*/
|
||||||
|
private val presetSelector = UIItemTextSelector(this,
|
||||||
|
kbx + (width - presetButtonWidth) / 2,
|
||||||
|
kby + 162 + 16,
|
||||||
|
ControlPresets.presetLabels.map { { it } },
|
||||||
|
ControlPresets.presetLabels.indexOf(App.getConfigString("control_preset_keyboard")),
|
||||||
|
presetButtonWidth,
|
||||||
|
clickToShowPalette = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val controlPalette = UIItemControlPaletteBaloon(this, (Toolkit.drawWidth - 500) / 2, kby + 219)
|
private val controlPalette = UIItemControlPaletteBaloon(this, (Toolkit.drawWidth - 500) / 2, kby + 227)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
||||||
keycaps.values.forEach { addUIitem(it) }
|
keycaps.values.forEach { addUIitem(it) }
|
||||||
updateKeycaps()
|
updateKeycaps()
|
||||||
|
|
||||||
buttonReset.clickOnceListener = { x, y ->
|
/*buttonReset.clickOnceListener = { x, y ->
|
||||||
resetKeyConfig()
|
resetKeyConfig()
|
||||||
updateKeycaps()
|
updateKeycaps()
|
||||||
|
}*/
|
||||||
|
|
||||||
|
presetSelector.selectionChangeListener = { index ->
|
||||||
|
App.setConfig("control_preset_keyboard", ControlPresets.presetLabels[index])
|
||||||
|
updateKeycaps()
|
||||||
}
|
}
|
||||||
|
|
||||||
// addUIitem(keyboardLayoutSelection)
|
// addUIitem(keyboardLayoutSelection)
|
||||||
@@ -152,18 +164,18 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
private fun updateKeycaps() {
|
private fun updateKeycaps() {
|
||||||
keycaps.values.forEach { it.symbolControl = null }
|
keycaps.values.forEach { it.symbolControl = null }
|
||||||
// read config and put icons. Item order irrelevant
|
// read config and put icons. Item order irrelevant
|
||||||
keycaps[App.getConfigInt("control_key_up")]?.symbolControl = Keebsym.UP
|
keycaps[ControlPresets.getKey("control_key_up")]?.symbolControl = Keebsym.UP
|
||||||
keycaps[App.getConfigInt("control_key_left")]?.symbolControl = Keebsym.LEFT
|
keycaps[ControlPresets.getKey("control_key_left")]?.symbolControl = Keebsym.LEFT
|
||||||
keycaps[App.getConfigInt("control_key_down")]?.symbolControl = Keebsym.DOWN
|
keycaps[ControlPresets.getKey("control_key_down")]?.symbolControl = Keebsym.DOWN
|
||||||
keycaps[App.getConfigInt("control_key_right")]?.symbolControl = Keebsym.RIGHT
|
keycaps[ControlPresets.getKey("control_key_right")]?.symbolControl = Keebsym.RIGHT
|
||||||
keycaps[App.getConfigInt("control_key_jump")]?.symbolControl = Keebsym.JUMP
|
keycaps[ControlPresets.getKey("control_key_jump")]?.symbolControl = Keebsym.JUMP
|
||||||
keycaps[App.getConfigInt("control_key_zoom")]?.symbolControl = Keebsym.ZOOM
|
keycaps[ControlPresets.getKey("control_key_zoom")]?.symbolControl = Keebsym.ZOOM
|
||||||
keycaps[App.getConfigInt("control_key_inventory")]?.symbolControl = Keebsym.INVENTORY
|
keycaps[ControlPresets.getKey("control_key_inventory")]?.symbolControl = Keebsym.INVENTORY
|
||||||
keycaps[App.getConfigInt("control_key_movementaux")]?.symbolControl = Keebsym.HOOK
|
keycaps[ControlPresets.getKey("control_key_movementaux")]?.symbolControl = Keebsym.HOOK
|
||||||
keycaps[App.getConfigInt("control_key_quicksel")]?.symbolControl = Keebsym.PIE
|
keycaps[ControlPresets.getKey("control_key_quicksel")]?.symbolControl = Keebsym.PIE
|
||||||
keycaps[App.getConfigInt("control_key_gamemenu")]?.symbolControl = Keebsym.MENU
|
keycaps[ControlPresets.getKey("control_key_gamemenu")]?.symbolControl = Keebsym.MENU
|
||||||
keycaps[App.getConfigInt("control_key_toggleime")]?.symbolControl = Keebsym.IME()
|
keycaps[ControlPresets.getKey("control_key_toggleime")]?.symbolControl = Keebsym.IME()
|
||||||
keycaps[App.getConfigInt("control_key_crafting")]?.symbolControl = Keebsym.CRAFTING
|
keycaps[ControlPresets.getKey("control_key_crafting")]?.symbolControl = Keebsym.CRAFTING
|
||||||
}
|
}
|
||||||
|
|
||||||
internal var keycapClicked = -13372
|
internal var keycapClicked = -13372
|
||||||
@@ -176,14 +188,14 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
override fun updateUI(delta: Float) {
|
override fun updateUI(delta: Float) {
|
||||||
uiItems.forEach {
|
uiItems.forEach {
|
||||||
it.update(delta)
|
it.update(delta)
|
||||||
if (it is UIItemKeycap && it.mousePushed) {
|
if (it is UIItemKeycap && it.mousePushed && ControlPresets.presetLabels[presetSelector.selection] == "Custom") {
|
||||||
it.selected = true
|
it.selected = true
|
||||||
// println("key ${it.key}; selected = ${it.selected}")
|
// println("key ${it.key}; selected = ${it.selected}")
|
||||||
keycapClicked = it.key ?: -13372
|
keycapClicked = it.key ?: -13372
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonReset.update(delta)
|
presetSelector.update(delta)
|
||||||
|
|
||||||
controlPalette.update(delta)
|
controlPalette.update(delta)
|
||||||
}
|
}
|
||||||
@@ -194,7 +206,7 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
// batch.color = fillCol
|
// batch.color = fillCol
|
||||||
// Toolkit.fillArea(batch, drawX, drawY, width, height)
|
// Toolkit.fillArea(batch, drawX, drawY, width, height)
|
||||||
uiItems.forEach { it.render(batch, camera) }
|
uiItems.forEach { it.render(batch, camera) }
|
||||||
buttonReset.render(batch, camera)
|
presetSelector.render(batch, camera)
|
||||||
|
|
||||||
// title
|
// title
|
||||||
// todo show "Keyboard"/"Gamepad" accordingly
|
// todo show "Keyboard"/"Gamepad" accordingly
|
||||||
@@ -215,21 +227,56 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setControlOf(key: Int, control: Int) {
|
fun setControlOf(key: Int, control: Int) {
|
||||||
|
if (App.getConfigString("control_preset_keyboard") != "Custom") {
|
||||||
|
System.err.println("[UIKeyboardControlPanel] cannot set a control if the preset is not 'Custom' (current preset: ${App.getConfigString("control_preset_keyboard")})")
|
||||||
|
return
|
||||||
|
}
|
||||||
if (control >= 0) {
|
if (control >= 0) {
|
||||||
App.setConfig(UIItemControlPaletteBaloon.indexToConfigKey[control]!!, key)
|
val controlName = UIItemControlPaletteBaloon.indexToConfigKey[control]!!
|
||||||
|
|
||||||
|
val conflicts = App.gameConfig.keySet.filter {
|
||||||
|
(it as String).startsWith("control_key_")
|
||||||
|
}.map {
|
||||||
|
(it as String).let { it to
|
||||||
|
try { (App.getConfigInt(it) == key) }
|
||||||
|
catch (_: ClassCastException) { false }
|
||||||
|
}
|
||||||
|
}.filter { it.second }.map { it.first }.firstOrNull()
|
||||||
|
|
||||||
|
println("[UIKeyboardControlPanel] key=$key, control=$controlName")
|
||||||
|
|
||||||
|
if (conflicts != null) {
|
||||||
|
val oldValue = App.getConfigInt(controlName)
|
||||||
|
App.setConfig(conflicts, oldValue)
|
||||||
|
|
||||||
|
println("[UIKeyboardControlPanel] set config $conflicts=$oldValue")
|
||||||
|
}
|
||||||
|
|
||||||
|
App.setConfig(controlName, key)
|
||||||
|
println("[UIKeyboardControlPanel] set config $controlName=$key")
|
||||||
}
|
}
|
||||||
updateKeycaps()
|
updateKeycaps()
|
||||||
|
|
||||||
|
Terrarum.ingame?.let {
|
||||||
|
it.onConfigChange()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
super.touchDown(screenX, screenY, pointer, button)
|
super.touchDown(screenX, screenY, pointer, button)
|
||||||
buttonReset.touchDown(screenX, screenY, pointer, button)
|
presetSelector.touchDown(screenX, screenY, pointer, button)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
super.touchUp(screenX, screenY, pointer, button)
|
super.touchUp(screenX, screenY, pointer, button)
|
||||||
buttonReset.touchUp(screenX, screenY, pointer, button)
|
presetSelector.touchUp(screenX, screenY, pointer, button)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun scrolled(amountX: Float, amountY: Float): Boolean {
|
||||||
|
super.scrolled(amountX, amountY)
|
||||||
|
presetSelector.scrolled(amountX, amountY)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ class UILoadDemoSavefiles(val remoCon: UIRemoCon) : Advanceable() {
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_up"))}${getKeycapPC(App.getConfigInt("control_key_down"))}" +
|
"${getKeycapPC(ControlPresets.getKey("control_key_up"))}${getKeycapPC(ControlPresets.getKey("control_key_down"))}" +
|
||||||
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
else
|
else
|
||||||
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
@@ -408,12 +408,12 @@ class UILoadDemoSavefiles(val remoCon: UIRemoCon) : Advanceable() {
|
|||||||
if (this.isVisible) {
|
if (this.isVisible) {
|
||||||
val cells = getCells()
|
val cells = getCells()
|
||||||
|
|
||||||
if ((keycode == Input.Keys.UP || keycode == App.getConfigInt("control_key_up")) && scrollTarget > 0) {
|
if ((keycode == Input.Keys.UP || keycode == ControlPresets.getKey("control_key_up")) && scrollTarget > 0) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget -= 1
|
scrollTarget -= 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
}
|
}
|
||||||
else if ((keycode == Input.Keys.DOWN || keycode == App.getConfigInt("control_key_down")) && scrollTarget < cells.size - savesVisible) {
|
else if ((keycode == Input.Keys.DOWN || keycode == ControlPresets.getKey("control_key_down")) && scrollTarget < cells.size - savesVisible) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget += 1
|
scrollTarget += 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_up"))}${getKeycapPC(App.getConfigInt("control_key_down"))}" +
|
"${getKeycapPC(ControlPresets.getKey("control_key_up"))}${getKeycapPC(ControlPresets.getKey("control_key_down"))}" +
|
||||||
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
else
|
else
|
||||||
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
@@ -249,12 +249,12 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
|
|||||||
if (this.isVisible) {
|
if (this.isVisible) {
|
||||||
val cells = playerCells
|
val cells = playerCells
|
||||||
|
|
||||||
if ((keycode == Input.Keys.UP || keycode == App.getConfigInt("control_key_up")) && scrollTarget > 0) {
|
if ((keycode == Input.Keys.UP || keycode == ControlPresets.getKey("control_key_up")) && scrollTarget > 0) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget -= 1
|
scrollTarget -= 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
}
|
}
|
||||||
else if ((keycode == Input.Keys.DOWN || keycode == App.getConfigInt("control_key_down")) && scrollTarget < cells.size - savesVisible) {
|
else if ((keycode == Input.Keys.DOWN || keycode == ControlPresets.getKey("control_key_down")) && scrollTarget < cells.size - savesVisible) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget += 1
|
scrollTarget += 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
|
|||||||
@@ -227,8 +227,8 @@ class UILoadManage(val full: UILoadSavegame) : UICanvas() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
MODE_DELETE -> {
|
MODE_DELETE -> {
|
||||||
Toolkit.drawTextCentered(batch, App.fontGame, Lang["MENU_LABEL_SAVE_WILL_BE_DELETED"], Toolkit.drawWidth, 0, full.titleTopGradEnd + full.cellInterval - 46)
|
Toolkit.drawTextCentered(batch, App.fontGame, Lang["MENU_LABEL_SAVE_WILL_BE_DELETED"], Toolkit.drawWidth, 0, full.titleTopGradEnd + full.cellInterval + SAVE_CELL_HEIGHT + 36)
|
||||||
Toolkit.drawTextCentered(batch, App.fontGame, Lang["MENU_LABEL_ARE_YOU_SURE"], Toolkit.drawWidth, 0, full.titleTopGradEnd + full.cellInterval + SAVE_CELL_HEIGHT + 36)
|
Toolkit.drawTextCentered(batch, App.fontGame, Lang["MENU_LABEL_ARE_YOU_SURE"], Toolkit.drawWidth, 0, full.titleTopGradEnd + full.cellInterval + SAVE_CELL_HEIGHT + 36 + 24)
|
||||||
|
|
||||||
delButtons.forEach { it.render(batch, camera) }
|
delButtons.forEach { it.render(batch, camera) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ import kotlin.math.roundToInt
|
|||||||
* Created by minjaesong on 2019-08-11.
|
* Created by minjaesong on 2019-08-11.
|
||||||
*/
|
*/
|
||||||
class UIScreenZoom : UICanvas(
|
class UIScreenZoom : UICanvas(
|
||||||
App.getConfigInt("control_key_zoom")
|
"control_key_zoom"
|
||||||
) {
|
) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
handler.allowESCtoClose = false
|
handler.allowESCtoClose = false
|
||||||
}
|
}
|
||||||
|
|
||||||
val zoomText = "${getKeycapPC(handler.toggleKeyLiteral!!)} $EMDASH Zoom Out"
|
val zoomText = "${getKeycapPC(handler.toggleKey!!)} $EMDASH Zoom Out"
|
||||||
|
|
||||||
override var width = App.fontGame.getWidth(zoomText)
|
override var width = App.fontGame.getWidth(zoomText)
|
||||||
override var height = App.fontGame.lineHeight.toInt()
|
override var height = App.fontGame.lineHeight.toInt()
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import kotlin.math.min
|
|||||||
* Created by minjaesong on 2019-07-08.
|
* Created by minjaesong on 2019-07-08.
|
||||||
*/
|
*/
|
||||||
internal class UIStorageChest : UICanvas(
|
internal class UIStorageChest : UICanvas(
|
||||||
toggleKeyLiteral = App.getConfigInt("control_key_inventory"),
|
toggleKeyLiteral = "control_key_inventory",
|
||||||
toggleButtonLiteral = App.getConfigInt("control_gamepad_start"),
|
toggleButtonLiteral = "control_gamepad_start",
|
||||||
), HasInventory {
|
), HasInventory {
|
||||||
|
|
||||||
lateinit var chestInventory: FixtureInventory
|
lateinit var chestInventory: FixtureInventory
|
||||||
@@ -175,7 +175,7 @@ internal class UIStorageChest : UICanvas(
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
else
|
else
|
||||||
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]} "
|
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]} "
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class UITierOneWatch() : UICanvas() {
|
|||||||
ELuptimer += delta
|
ELuptimer += delta
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouseUp || Gdx.input.isKeyPressed(App.getConfigInt("control_key_interact"))) {
|
if (mouseUp || Gdx.input.isKeyPressed(ControlPresets.getKey("control_key_interact"))) {
|
||||||
ELuptimer = 0f
|
ELuptimer = 0f
|
||||||
ELon = true
|
ELon = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class UITitleModules(val remoCon: UIRemoCon) : UICanvas() {
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_up"))}${getKeycapPC(App.getConfigInt("control_key_down"))}" +
|
"${getKeycapPC(ControlPresets.getKey("control_key_up"))}${getKeycapPC(ControlPresets.getKey("control_key_down"))}" +
|
||||||
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
" ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
else
|
else
|
||||||
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
"${getKeycapConsole('R')} ${Lang["MENU_CONTROLS_SCROLL"]}"
|
||||||
@@ -206,12 +206,12 @@ class UITitleModules(val remoCon: UIRemoCon) : UICanvas() {
|
|||||||
|
|
||||||
override fun keyDown(keycode: Int): Boolean {
|
override fun keyDown(keycode: Int): Boolean {
|
||||||
if (this.isVisible) {
|
if (this.isVisible) {
|
||||||
if ((keycode == Input.Keys.UP || keycode == App.getConfigInt("control_key_up")) && scrollTarget > 0) {
|
if ((keycode == Input.Keys.UP || keycode == ControlPresets.getKey("control_key_up")) && scrollTarget > 0) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget -= 1
|
scrollTarget -= 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
}
|
}
|
||||||
else if ((keycode == Input.Keys.DOWN || keycode == App.getConfigInt("control_key_down")) && scrollTarget < moduleCells.size - savesVisible) {
|
else if ((keycode == Input.Keys.DOWN || keycode == ControlPresets.getKey("control_key_down")) && scrollTarget < moduleCells.size - savesVisible) {
|
||||||
scrollFrom = listScroll
|
scrollFrom = listScroll
|
||||||
scrollTarget += 1
|
scrollTarget += 1
|
||||||
scrollAnimCounter = 0f
|
scrollAnimCounter = 0f
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ object UITitleRemoConYaml {
|
|||||||
|
|
||||||
// todo add MENU_IO_IMPORT
|
// todo add MENU_IO_IMPORT
|
||||||
val injectedMenuSingleCharSel = """
|
val injectedMenuSingleCharSel = """
|
||||||
- MENU_IO_IMPORT
|
- MENU_IO_IMPORT : net.torvald.terrarum.modulebasegame.ui.UIImportAvatar
|
||||||
- CONTEXT_CHARACTER_NEW : net.torvald.terrarum.modulebasegame.ui.UINewCharacter
|
- CONTEXT_CHARACTER_NEW : net.torvald.terrarum.modulebasegame.ui.UINewCharacter
|
||||||
- MENU_LABEL_RETURN
|
- MENU_LABEL_RETURN
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ package net.torvald.terrarum.modulebasegame.ui
|
|||||||
import com.badlogic.gdx.graphics.Camera
|
import com.badlogic.gdx.graphics.Camera
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.*
|
||||||
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
|
||||||
import net.torvald.terrarum.gameworld.WorldTime.Companion.MONTH_LENGTH
|
import net.torvald.terrarum.gameworld.WorldTime.Companion.MONTH_LENGTH
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
@@ -18,8 +15,8 @@ import net.torvald.unicode.getKeycapPC
|
|||||||
* Created by minjaesong on 2023-08-15.
|
* Created by minjaesong on 2023-08-15.
|
||||||
*/
|
*/
|
||||||
class UIWallCalendar : UICanvas(
|
class UIWallCalendar : UICanvas(
|
||||||
toggleKeyLiteral = App.getConfigInt("control_key_inventory"),
|
toggleKeyLiteral = "control_key_inventory",
|
||||||
toggleButtonLiteral = App.getConfigInt("control_gamepad_start"),
|
toggleButtonLiteral = "control_gamepad_start",
|
||||||
) {
|
) {
|
||||||
private val yearCellWidth = 200
|
private val yearCellWidth = 200
|
||||||
private val cellWidth = 80
|
private val cellWidth = 80
|
||||||
@@ -36,7 +33,7 @@ class UIWallCalendar : UICanvas(
|
|||||||
private val SP = "\u3000 "
|
private val SP = "\u3000 "
|
||||||
val controlHelp: String
|
val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
else
|
else
|
||||||
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.ui
|
package net.torvald.terrarum.modulebasegame.ui
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Camera
|
import com.badlogic.gdx.graphics.Camera
|
||||||
import com.badlogic.gdx.graphics.Color
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
@@ -31,8 +30,8 @@ import java.util.UUID
|
|||||||
* Created by minjaesong on 2023-05-19.
|
* Created by minjaesong on 2023-05-19.
|
||||||
*/
|
*/
|
||||||
class UIWorldPortal : UICanvas(
|
class UIWorldPortal : UICanvas(
|
||||||
toggleKeyLiteral = App.getConfigInt("control_key_inventory"),
|
toggleKeyLiteral = "control_key_inventory",
|
||||||
toggleButtonLiteral = App.getConfigInt("control_gamepad_start"),
|
toggleButtonLiteral = "control_gamepad_start",
|
||||||
) {
|
) {
|
||||||
|
|
||||||
override var width: Int = Toolkit.drawWidth
|
override var width: Int = Toolkit.drawWidth
|
||||||
@@ -54,7 +53,7 @@ class UIWorldPortal : UICanvas(
|
|||||||
private val SP = "\u3000 "
|
private val SP = "\u3000 "
|
||||||
val portalListingControlHelp: String
|
val portalListingControlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
else
|
else
|
||||||
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]}" +
|
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]}" +
|
||||||
"$SP${App.gamepadLabelLT} ${Lang["GAME_WORLD_SEARCH"]}" +
|
"$SP${App.gamepadLabelLT} ${Lang["GAME_WORLD_SEARCH"]}" +
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ class UIWorldPortalCargo(val full: UIWorldPortal) : UICanvas(), HasInventory {
|
|||||||
|
|
||||||
private val controlHelp: String
|
private val controlHelp: String
|
||||||
get() = if (App.environment == RunningEnvironment.PC)
|
get() = if (App.environment == RunningEnvironment.PC)
|
||||||
"${getKeycapPC(App.getConfigInt("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
else
|
else
|
||||||
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]} "
|
"${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]} "
|
||||||
|
|
||||||
|
|||||||
@@ -4,27 +4,26 @@ import net.torvald.terrarum.savegame.toBigEndian
|
|||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
|
|
||||||
/**
|
/** My own string set that:
|
||||||
* Ascii85 implementation with my own character table based on RFC 1924. Will NOT truncate '00000' into something else;
|
* - no "/": avoids nonstandard JSON comment key which GDX will happily parse away
|
||||||
* just gzip the inputstream instead!
|
* - no "\": you know what I mean\\intention
|
||||||
|
* - no "$": avoids Kotlin string template
|
||||||
|
* - no "[{]},": even the dumbest parser can comprehend the output
|
||||||
*/
|
*/
|
||||||
object Ascii85 {
|
open class Ascii85Codec(private val CHAR_TABLE: String = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#%&'()*+-.:;<=>?@^_`|~") {
|
||||||
/** My own string set that:
|
init {
|
||||||
* - no "/": avoids nonstandard JSON comment key which GDX will happily parse away
|
if (CHAR_TABLE.length != 85) throw IllegalArgumentException("CHAR_TABLE is not 85 chars long")
|
||||||
* - no "\": you know what I mean\\intention
|
}
|
||||||
* - no "$": avoids Kotlin string template
|
|
||||||
* - no "[{]},": even the dumbest parser can comprehend the output
|
|
||||||
*/
|
|
||||||
private const val CHAR_TABLE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#%&'()*+-.:;<=>?@^_`|~"
|
|
||||||
/** As per Adobe standard */
|
/** As per Adobe standard */
|
||||||
//private val CHAR_TABLE = (33 until (33+85)).toList().map { it.toChar() }.joinToString("") // testing only!
|
//private val CHAR_TABLE = (33 until (33+85)).toList().map { it.toChar() }.joinToString("") // testing only!
|
||||||
|
|
||||||
private val INVERSE_TABLE = LongArray(127)
|
private val INVERSE_TABLE = LongArray(127)
|
||||||
|
|
||||||
/** Int of `-1` */
|
/** Int of `-1` */
|
||||||
const val PAD_BYTE = -1
|
val PAD_BYTE = -1
|
||||||
/** Null-character (`\0`) */
|
/** Null-character (`\0`) */
|
||||||
const val PAD_CHAR = 0.toChar()
|
val PAD_CHAR = 0.toChar()
|
||||||
|
|
||||||
private val INTERNAL_PAD_BYTE = 0
|
private val INTERNAL_PAD_BYTE = 0
|
||||||
private val INTERNAL_PAD_CHAR = CHAR_TABLE.last()
|
private val INTERNAL_PAD_CHAR = CHAR_TABLE.last()
|
||||||
@@ -97,10 +96,10 @@ object Ascii85 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val sum = (INVERSE_TABLE[s1.toInt()] * 52200625) +
|
val sum = (INVERSE_TABLE[s1.toInt()] * 52200625) +
|
||||||
(INVERSE_TABLE[s2.toInt()] * 614125) +
|
(INVERSE_TABLE[s2.toInt()] * 614125) +
|
||||||
(INVERSE_TABLE[s3.toInt()] * 7225) +
|
(INVERSE_TABLE[s3.toInt()] * 7225) +
|
||||||
(INVERSE_TABLE[s4.toInt()] * 85) +
|
(INVERSE_TABLE[s4.toInt()] * 85) +
|
||||||
INVERSE_TABLE[s5.toInt()]
|
INVERSE_TABLE[s5.toInt()]
|
||||||
return ByteArray(4 - padLen) { sum.ushr((3 - it) * 8).and(255).toByte() }
|
return ByteArray(4 - padLen) { sum.ushr((3 - it) * 8).and(255).toByte() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,6 +136,12 @@ object Ascii85 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ascii85 implementation with my own character table based on RFC 1924. Will NOT truncate '00000' into something else;
|
||||||
|
* just gzip the inputstream instead!
|
||||||
|
*/
|
||||||
|
object Ascii85 : Ascii85Codec()
|
||||||
|
|
||||||
fun UUID.toAscii85() =
|
fun UUID.toAscii85() =
|
||||||
Ascii85.encodeBytes(this.mostSignificantBits.toBigEndian() + this.leastSignificantBits.toBigEndian())
|
Ascii85.encodeBytes(this.mostSignificantBits.toBigEndian() + this.leastSignificantBits.toBigEndian())
|
||||||
fun String.ascii85toUUID(): UUID {
|
fun String.ascii85toUUID(): UUID {
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
val soldeg = WeatherMixer.forceSolarElev ?: world?.worldTime?.solarElevationDeg
|
val soldeg = WeatherMixer.forceSolarElev ?: world?.worldTime?.solarElevationDeg
|
||||||
val soldegStr = (soldeg ?: 0.0).toIntAndFrac(3,2)
|
val soldegStr = (soldeg ?: 0.0).toIntAndFrac(3,2)
|
||||||
val soldegNeg = ((soldeg ?: 0.0) >= 0.0).toInt()
|
val soldegNeg = ((soldeg ?: 0.0) >= 0.0).toInt()
|
||||||
val turbidity = WeatherMixer.forceTurbidity ?: WeatherMixer.turbidity
|
val turbidity = (WeatherMixer.forceTurbidity ?: WeatherMixer.turbidity).toIntAndFrac(1, 4)
|
||||||
|
|
||||||
val soldegCol = if (WeatherMixer.forceSolarElev != null) ccO else ccG
|
val soldegCol = if (WeatherMixer.forceSolarElev != null) ccO else ccG
|
||||||
val turbCol = if (WeatherMixer.forceTurbidity != null) ccO else ccG
|
val turbCol = if (WeatherMixer.forceTurbidity != null) ccO else ccG
|
||||||
@@ -292,15 +292,17 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
|
|
||||||
if (ingame != null) {
|
if (ingame != null) {
|
||||||
App.fontSmallNumbers.draw(batch, "${ccY}Actors total $ccG${ingame!!.actorContainerActive.size + ingame!!.actorContainerInactive.size}",
|
App.fontSmallNumbers.draw(batch, "${ccY}Actors total $ccG${ingame!!.actorContainerActive.size + ingame!!.actorContainerInactive.size}",
|
||||||
TinyAlphNum.W * 2f, App.scr.height - TinyAlphNum.H * 2f)
|
TinyAlphNum.W * 2f, App.scr.height - TinyAlphNum.H * 2f)
|
||||||
App.fontSmallNumbers.draw(batch, "${ccY}Active $ccG${ingame!!.actorContainerActive.size}",
|
App.fontSmallNumbers.draw(batch, "${ccY}Active $ccG${ingame!!.actorContainerActive.size}",
|
||||||
(TinyAlphNum.W * 2 + 17 * 8).toFloat(), App.scr.height - TinyAlphNum.H * 2f)
|
TinyAlphNum.W * 2f + (17 * 8), App.scr.height - TinyAlphNum.H * 2f)
|
||||||
App.fontSmallNumbers.draw(batch, "${ccY}Dormant $ccG${ingame!!.actorContainerInactive.size}",
|
App.fontSmallNumbers.draw(batch, "${ccY}Dormant $ccG${ingame!!.actorContainerInactive.size}",
|
||||||
(TinyAlphNum.W * 2 + 28 * 8).toFloat(), App.scr.height - TinyAlphNum.H * 2f)
|
TinyAlphNum.W * 2f + (28 * 8), App.scr.height - TinyAlphNum.H * 2f)
|
||||||
if (ingame is TerrarumIngame) {
|
if (ingame is TerrarumIngame) {
|
||||||
App.fontSmallNumbers.draw(batch, "${ccM}Particles $ccG${(ingame as TerrarumIngame).particlesActive}",
|
App.fontSmallNumbers.draw(batch, "${ccM}Particles $ccG${(ingame as TerrarumIngame).particlesActive}$ccY/$ccG${(ingame as TerrarumIngame).PARTICLES_MAX}",
|
||||||
(TinyAlphNum.W * 2 + 41 * 8).toFloat(), App.scr.height - TinyAlphNum.H * 2f)
|
TinyAlphNum.W * 2f, App.scr.height - TinyAlphNum.H * 4f)
|
||||||
}
|
}
|
||||||
|
App.fontSmallNumbers.draw(batch, "${ccM}Clouds $ccG${WeatherMixer.cloudsSpawned}$ccY/$ccG${WeatherMixer.cloudSpawnMax}",
|
||||||
|
TinyAlphNum.W * 2f + (18 * 8), App.scr.height - TinyAlphNum.H * 4f)
|
||||||
}
|
}
|
||||||
|
|
||||||
App.fontSmallNumbers.draw(batch, "${ccY}Actors rendering $ccG${IngameRenderer.renderingActorsCount}",
|
App.fontSmallNumbers.draw(batch, "${ccY}Actors rendering $ccG${IngameRenderer.renderingActorsCount}",
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ import kotlin.math.roundToInt
|
|||||||
* Created by minjaesong on 2015-12-31.
|
* Created by minjaesong on 2015-12-31.
|
||||||
*/
|
*/
|
||||||
abstract class UICanvas(
|
abstract class UICanvas(
|
||||||
toggleKeyLiteral: Int? = null, toggleButtonLiteral: Int? = null,
|
toggleKeyLiteral: String? = null, toggleButtonLiteral: String? = null,
|
||||||
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
||||||
customPositioning: Boolean = false, // mainly used by vital meter
|
customPositioning: Boolean = false, // mainly used by vital meter
|
||||||
doNotWarnConstant: Boolean = false
|
doNotWarnConstant: Boolean = false
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.Color
|
|||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.ControlPresets
|
||||||
import net.torvald.terrarum.FlippingSpriteBatch
|
import net.torvald.terrarum.FlippingSpriteBatch
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
@@ -25,8 +26,8 @@ import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
|||||||
* Created by minjaesong on 2015-12-31.
|
* Created by minjaesong on 2015-12-31.
|
||||||
*/
|
*/
|
||||||
class UIHandler(//var UI: UICanvas,
|
class UIHandler(//var UI: UICanvas,
|
||||||
var toggleKeyLiteral: Int? = null,
|
var toggleKeyLiteral: String? = null, // string key of the config
|
||||||
var toggleButtonLiteral: Int? = null,
|
var toggleButtonLiteral: String? = null, // string key of the config
|
||||||
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
// UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int))
|
||||||
var customPositioning: Boolean = false, // mainly used by vital meter
|
var customPositioning: Boolean = false, // mainly used by vital meter
|
||||||
var doNotWarnConstant: Boolean = false,
|
var doNotWarnConstant: Boolean = false,
|
||||||
@@ -130,12 +131,13 @@ void main() {
|
|||||||
//UI.handler = this
|
//UI.handler = this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ControlPresets.getKey(toggleKeyLiteral)
|
||||||
private val toggleKey: Int?; get() = toggleKeyLiteral // to support in-screen keybind changing
|
val toggleKey: Int?; get() = ControlPresets.getKey(toggleKeyLiteral).let { if (it == -1) null else it } // to support in-screen keybind changing
|
||||||
private val toggleButton: Int?; get() = toggleButtonLiteral // to support in-screen keybind changing
|
// ControlPresets.getKey(toggleButtonLiteral)
|
||||||
|
val toggleButton: Int?; get() = ControlPresets.getKey(toggleButtonLiteral).let { if (it == -1) null else it } // to support in-screen keybind changing
|
||||||
|
|
||||||
|
|
||||||
val toggleKeyExtra: ArrayList<() -> Int> = arrayListOf()
|
val toggleKeyExtra: ArrayList<String> = arrayListOf()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a function that works with UIHandler.
|
* Takes a function that works with UIHandler.
|
||||||
@@ -207,8 +209,8 @@ void main() {
|
|||||||
else uiTogglerFunctionDefault!!.invoke(this)
|
else uiTogglerFunctionDefault!!.invoke(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleKeyExtra.forEachIndexed { index, getKey ->
|
toggleKeyExtra.forEachIndexed { index, control ->
|
||||||
if (Gdx.input.isKeyJustPressed(getKey())) {
|
if (Gdx.input.isKeyJustPressed(ControlPresets.getKey(control))) {
|
||||||
toggleKeyExtraAction[index].invoke(this)
|
toggleKeyExtraAction[index].invoke(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -443,7 +443,7 @@ class UIItemTextLineInput(
|
|||||||
|
|
||||||
if (!mouseDown) mouseLatched = false
|
if (!mouseDown) mouseLatched = false
|
||||||
|
|
||||||
imeOn = KeyToggler.isOn(App.getConfigInt("control_key_toggleime"))
|
imeOn = KeyToggler.isOn(ControlPresets.getKey("control_key_toggleime"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,7 +468,7 @@ class UIItemTextLineInput(
|
|||||||
endComposing()
|
endComposing()
|
||||||
|
|
||||||
imeOn = !imeOn
|
imeOn = !imeOn
|
||||||
KeyToggler.forceSet(App.getConfigInt("control_key_toggleime"), imeOn)
|
KeyToggler.forceSet(ControlPresets.getKey("control_key_toggleime"), imeOn)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetIME() {
|
private fun resetIME() {
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
package net.torvald.terrarum.weather
|
package net.torvald.terrarum.weather
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
import com.badlogic.gdx.math.Vector3
|
||||||
|
import com.badlogic.gdx.utils.JsonValue
|
||||||
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.GdxColorMap
|
import net.torvald.terrarum.GdxColorMap
|
||||||
import java.util.*
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: Colour maps are likely to have sparse data points
|
* Note: Colour maps are likely to have sparse data points
|
||||||
@@ -12,10 +17,49 @@ import java.util.*
|
|||||||
* Created by minjaesong on 2016-07-11.
|
* Created by minjaesong on 2016-07-11.
|
||||||
*/
|
*/
|
||||||
data class BaseModularWeather(
|
data class BaseModularWeather(
|
||||||
var skyboxGradColourMap: GdxColorMap, // row 0: skybox grad top, row 1: skybox grad bottom, row 2: sunlight (RGBA)
|
val json: JsonValue,
|
||||||
val daylightClut: GdxColorMap,
|
var skyboxGradColourMap: GdxColorMap, // row 0: skybox grad top, row 1: skybox grad bottom, row 2: sunlight (RGBA)
|
||||||
val classification: String,
|
val daylightClut: GdxColorMap,
|
||||||
var extraImages: ArrayList<Texture>,
|
val classification: String,
|
||||||
val mixFrom: String? = null,
|
val cloudChance: Float,
|
||||||
val mixPercentage: Double? = null
|
val windSpeed: Float,
|
||||||
)
|
val windSpeedVariance: Float,
|
||||||
|
val cloudGamma: Vector2,
|
||||||
|
val cloudGammaVariance: Vector2,
|
||||||
|
var clouds: List<CloudProps>, // sorted by CloudProps.probability
|
||||||
|
|
||||||
|
val mixFrom: String? = null,
|
||||||
|
val mixPercentage: Double? = null,
|
||||||
|
|
||||||
|
var forceWindVec: Vector3? = null
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* @param rnd random number between -1 and +1
|
||||||
|
*/
|
||||||
|
fun getRandomWindSpeed(rnd: Float): Float {
|
||||||
|
val v = 1f + rnd.absoluteValue * windSpeedVariance
|
||||||
|
return if (rnd < 0) windSpeed / v else windSpeed * v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class CloudProps(
|
||||||
|
val category: String,
|
||||||
|
val spriteSheet: TextureRegionPack,
|
||||||
|
val probability: Float,
|
||||||
|
val baseScale: Float,
|
||||||
|
val scaleVariance: Float,
|
||||||
|
val altLow: Float,
|
||||||
|
val altHigh: Float,
|
||||||
|
) {
|
||||||
|
init {
|
||||||
|
spriteSheet.texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param rnd random number between -1 and +1
|
||||||
|
*/
|
||||||
|
fun getCloudScaleVariance(rnd: Float): Float {
|
||||||
|
val v = 1f + rnd.absoluteValue * scaleVariance
|
||||||
|
return if (rnd < 0) baseScale / v else baseScale * v
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,11 @@ package net.torvald.terrarum.weather
|
|||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.graphics.*
|
import com.badlogic.gdx.graphics.*
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
import com.badlogic.gdx.math.Vector3
|
||||||
|
import com.badlogic.gdx.utils.JsonValue
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.gdx.graphics.Cvec
|
import net.torvald.gdx.graphics.Cvec
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
@@ -16,9 +20,18 @@ import net.torvald.terrarum.gameworld.WorldTime.Companion.DAY_LENGTH
|
|||||||
import net.torvald.terrarum.RNGConsumer
|
import net.torvald.terrarum.RNGConsumer
|
||||||
import net.torvald.terrarum.clut.Skybox
|
import net.torvald.terrarum.clut.Skybox
|
||||||
import net.torvald.terrarum.utils.JsonFetcher
|
import net.torvald.terrarum.utils.JsonFetcher
|
||||||
|
import net.torvald.terrarum.utils.forEachSiblings
|
||||||
|
import net.torvald.terrarum.weather.WeatherObjectCloud.Companion.ALPHA_ROLLOFF_Z
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
import net.torvald.util.SortedArrayList
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileFilter
|
import java.io.FileFilter
|
||||||
|
import java.lang.Double.doubleToLongBits
|
||||||
|
import java.lang.Math.toDegrees
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
import kotlin.math.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently there is a debate whether this module must be part of the engine or the basegame
|
* Currently there is a debate whether this module must be part of the engine or the basegame
|
||||||
@@ -50,10 +63,11 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
lateinit var mixedWeather: BaseModularWeather
|
lateinit var mixedWeather: BaseModularWeather
|
||||||
|
|
||||||
val globalLightNow = Cvec(0)
|
val globalLightNow = Cvec(0)
|
||||||
|
private val moonlightMax = Cvec(0.23f, 0.24f, 0.25f, 0.21f) // actual moonlight is around ~4100K but our mesopic vision makes it appear blueish (wikipedia: Purkinje effect)
|
||||||
|
|
||||||
// Weather indices
|
// Weather indices
|
||||||
const val WEATHER_GENERIC = "generic"
|
const val WEATHER_GENERIC = "generic"
|
||||||
const val WEATHER_GENERIC_RAIN = "genericrain"
|
const val WEATHER_OVERCAST = "overcast"
|
||||||
// TODO add weather classification indices manually
|
// TODO add weather classification indices manually
|
||||||
|
|
||||||
// TODO to save from GL overhead, store lightmap to array; use GdxColorMap
|
// TODO to save from GL overhead, store lightmap to array; use GdxColorMap
|
||||||
@@ -68,16 +82,23 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
it.texture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat)
|
it.texture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val shaderBlendMax = App.loadShaderFromClasspath("shaders/blendSkyboxStars.vert", "shaders/blendSkyboxStars.frag")
|
private val shaderAstrum = App.loadShaderFromClasspath("shaders/blendSkyboxStars.vert", "shaders/blendSkyboxStars.frag")
|
||||||
|
private val shaderClouds = App.loadShaderFromClasspath("shaders/default.vert", "shaders/clouds.frag")
|
||||||
|
|
||||||
private var astrumOffX = 0f
|
private var astrumOffX = 0f
|
||||||
private var astrumOffY = 0f
|
private var astrumOffY = 0f
|
||||||
|
|
||||||
private val moonlightMax = Cvec(0.23f, 0.24f, 0.25f, 0.21f) // actual moonlight is around ~4100K but our mesopic vision makes it appear blueish (wikipedia: Purkinje effect)
|
private val clouds = SortedArrayList<WeatherObjectCloud>()
|
||||||
|
var cloudsSpawned = 0; private set
|
||||||
|
private var windVector = Vector3(-1f, 0f, 0.1f) // this is a direction vector
|
||||||
|
val cloudSpawnMax: Int
|
||||||
|
get() = 256 shl (App.getConfigInt("maxparticles") / 256)
|
||||||
|
|
||||||
override fun loadFromSave(s0: Long, s1: Long) {
|
override fun loadFromSave(s0: Long, s1: Long) {
|
||||||
super.loadFromSave(s0, s1)
|
super.loadFromSave(s0, s1)
|
||||||
|
currentWeather = weatherList[WEATHER_GENERIC]!![0]
|
||||||
internalReset(s0, s1)
|
internalReset(s0, s1)
|
||||||
|
initClouds()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun internalReset() = internalReset(RNG.state0, RNG.state1)
|
fun internalReset() = internalReset(RNG.state0, RNG.state1)
|
||||||
@@ -90,6 +111,15 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
astrumOffX = s0.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionWidth
|
astrumOffX = s0.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionWidth
|
||||||
astrumOffY = s1.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionHeight
|
astrumOffY = s1.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionHeight
|
||||||
|
|
||||||
|
clouds.clear()
|
||||||
|
cloudsSpawned = 0
|
||||||
|
windVector = Vector3(-0.98f, 0f, 0.21f)
|
||||||
|
|
||||||
|
windDirWindow = null
|
||||||
|
windSpeedWindow = null
|
||||||
|
|
||||||
|
oldCamPos.set(WorldCamera.camVector)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -121,6 +151,7 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
// initialise
|
// initialise
|
||||||
try {
|
try {
|
||||||
|
weatherList["titlescreen"] = arrayListOf(weatherList[WEATHER_GENERIC]!![0].copy(windSpeed = 1f))
|
||||||
currentWeather = weatherList[WEATHER_GENERIC]!![0]
|
currentWeather = weatherList[WEATHER_GENERIC]!![0]
|
||||||
nextWeather = getRandomWeather(WEATHER_GENERIC)
|
nextWeather = getRandomWeather(WEATHER_GENERIC)
|
||||||
}
|
}
|
||||||
@@ -128,10 +159,16 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|
||||||
val defaultWeather = BaseModularWeather(
|
val defaultWeather = BaseModularWeather(
|
||||||
|
JsonValue(JsonValue.ValueType.`object`),
|
||||||
GdxColorMap(1, 3, Color(0x55aaffff), Color(0xaaffffff.toInt()), Color.WHITE),
|
GdxColorMap(1, 3, Color(0x55aaffff), Color(0xaaffffff.toInt()), Color.WHITE),
|
||||||
GdxColorMap(2, 2, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE),
|
GdxColorMap(2, 2, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE),
|
||||||
"default",
|
"default",
|
||||||
ArrayList<Texture>()
|
0f,
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
Vector2(1f, 1f),
|
||||||
|
Vector2(0f, 0f),
|
||||||
|
listOf()
|
||||||
)
|
)
|
||||||
|
|
||||||
currentWeather = defaultWeather
|
currentWeather = defaultWeather
|
||||||
@@ -147,6 +184,9 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
// currentWeather = weatherList[WEATHER_GENERIC]!![0] // force set weather
|
// currentWeather = weatherList[WEATHER_GENERIC]!![0] // force set weather
|
||||||
|
|
||||||
|
updateWind(delta, world)
|
||||||
|
updateClouds(delta, world)
|
||||||
|
|
||||||
|
|
||||||
if (!globalLightOverridden) {
|
if (!globalLightOverridden) {
|
||||||
world.globalLight = WeatherMixer.globalLightNow
|
world.globalLight = WeatherMixer.globalLightNow
|
||||||
@@ -154,6 +194,328 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FloatArray.shiftAndPut(f: Float) {
|
||||||
|
for (k in 1 until this.size) {
|
||||||
|
this[k-1] = this[k]
|
||||||
|
}
|
||||||
|
this[this.lastIndex] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
private val PI = 3.1415927f
|
||||||
|
private val TWO_PI = 6.2831855f
|
||||||
|
private val THREE_PI = 9.424778f
|
||||||
|
|
||||||
|
private var windDirWindow: FloatArray? = null
|
||||||
|
private var windSpeedWindow: FloatArray? = null
|
||||||
|
private val WIND_DIR_TIME_UNIT = 14400 // every 4hr
|
||||||
|
private val WIND_SPEED_TIME_UNIT = 3600 // every 1hr
|
||||||
|
private var windDirAkku = 0 // only needed if timeDelta is not divisible by WIND_TIME_UNIT
|
||||||
|
private var windSpeedAkku = 0
|
||||||
|
|
||||||
|
// see: https://stackoverflow.com/questions/2708476/rotation-interpolation/14498790#14498790
|
||||||
|
private fun getShortestAngle(start: Float, end: Float) =
|
||||||
|
(((((end - if (start < 0f) TWO_PI + start else start) % TWO_PI) + THREE_PI) % TWO_PI) - PI).let {
|
||||||
|
if (it > PI) it - TWO_PI else it
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateWind(delta: Float, world: GameWorld) {
|
||||||
|
if (windDirWindow == null) {
|
||||||
|
windDirWindow = FloatArray(4) { takeUniformRand(-PI..PI) } // completely random regardless of the seed
|
||||||
|
}
|
||||||
|
if (windSpeedWindow == null) {
|
||||||
|
windSpeedWindow = FloatArray(4) { currentWeather.getRandomWindSpeed(takeTriangularRand(-1f..1f)) } // completely random regardless of the seed
|
||||||
|
}
|
||||||
|
|
||||||
|
val windDirStep = windDirAkku / WIND_DIR_TIME_UNIT.toFloat()
|
||||||
|
val windSpeedStep = windSpeedAkku / WIND_SPEED_TIME_UNIT.toFloat()
|
||||||
|
|
||||||
|
// val angle0 = windDirWindow[0]
|
||||||
|
// val angle1 = getShortestAngle(angle0, windDirWindow[1])
|
||||||
|
// val angle2 = getShortestAngle(angle1, windDirWindow[2])
|
||||||
|
// val angle3 = getShortestAngle(angle2, windDirWindow[3])
|
||||||
|
// val fixedAngles = floatArrayOf(angle0, angle1, angle2, angle3)
|
||||||
|
|
||||||
|
val currentWindDir = FastMath.interpolateCatmullRom(windDirStep, windDirWindow)
|
||||||
|
val currentWindSpeed = FastMath.interpolateCatmullRom(windSpeedStep, windSpeedWindow)
|
||||||
|
/*
|
||||||
|
printdbg(this,
|
||||||
|
"dir ${Math.toDegrees(currentWindDir.toDouble()).roundToInt()}\t" +
|
||||||
|
"spd ${currentWindSpeed.times(10f).roundToInt().div(10f)}\t " +
|
||||||
|
"dirs ${windDirWindow!!.map { Math.toDegrees(it.toDouble()).roundToInt() }} ${windDirStep.times(100).roundToInt()}\t" +
|
||||||
|
"spds ${windSpeedWindow!!.map { it.times(10f).roundToInt().div(10f) }} ${windSpeedStep.times(100).roundToInt()}"
|
||||||
|
)*/
|
||||||
|
|
||||||
|
if (currentWeather.forceWindVec != null) {
|
||||||
|
windVector.set(currentWeather.forceWindVec)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
windVector.set(
|
||||||
|
cos(currentWindDir) * currentWindSpeed,
|
||||||
|
0f,
|
||||||
|
sin(currentWindDir) * currentWindSpeed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
while (windDirAkku >= WIND_DIR_TIME_UNIT) {
|
||||||
|
windDirAkku -= WIND_DIR_TIME_UNIT
|
||||||
|
windDirWindow!!.shiftAndPut(takeUniformRand(-PI..PI))
|
||||||
|
}
|
||||||
|
while (windSpeedAkku >= WIND_SPEED_TIME_UNIT) {
|
||||||
|
windSpeedAkku -= WIND_SPEED_TIME_UNIT
|
||||||
|
windSpeedWindow!!.shiftAndPut(currentWeather.getRandomWindSpeed(takeTriangularRand(-1f..1f)))
|
||||||
|
}
|
||||||
|
|
||||||
|
windDirAkku += world.worldTime.timeDelta
|
||||||
|
windSpeedAkku += world.worldTime.timeDelta
|
||||||
|
}
|
||||||
|
|
||||||
|
private val cloudParallaxMultY = -0.035f
|
||||||
|
private val cloudParallaxMultX = -0.035f
|
||||||
|
private var cloudUpdateAkku = 0f
|
||||||
|
private val oldCamPos = Vector2(0f, 0f)
|
||||||
|
private val camDelta = Vector2(0f, 0f)
|
||||||
|
|
||||||
|
val oobMarginR = 1.5f * App.scr.wf
|
||||||
|
val oobMarginL = -0.5f * App.scr.wf
|
||||||
|
private val oobMarginY = -0.5f * App.scr.hf
|
||||||
|
|
||||||
|
private val DEBUG_CAUSE_OF_DESPAWN = false
|
||||||
|
|
||||||
|
private fun updateClouds(delta: Float, world: GameWorld) {
|
||||||
|
val camvec = WorldCamera.camVector
|
||||||
|
val camvec2 = camvec.cpy()
|
||||||
|
val testCamDelta = camvec.cpy().sub(oldCamPos)
|
||||||
|
|
||||||
|
if (testCamDelta.x.absoluteValue > world.width * TILE_SIZEF / 2f) {
|
||||||
|
if (testCamDelta.x >= 0)
|
||||||
|
camvec2.x -= world.width * TILE_SIZEF
|
||||||
|
else
|
||||||
|
camvec2.x += world.width * TILE_SIZEF
|
||||||
|
|
||||||
|
testCamDelta.set(camvec2.sub(oldCamPos))
|
||||||
|
}
|
||||||
|
|
||||||
|
camDelta.set(testCamDelta)
|
||||||
|
|
||||||
|
|
||||||
|
val cloudChanceEveryMin = 60f / (currentWeather.cloudChance * currentWeather.windSpeed) // if chance = 0, the result will be +inf
|
||||||
|
|
||||||
|
while (cloudUpdateAkku >= cloudChanceEveryMin) {
|
||||||
|
cloudUpdateAkku -= cloudChanceEveryMin
|
||||||
|
tryToSpawnCloud(currentWeather)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var immDespawnCount = 0
|
||||||
|
val immDespawnCauses = ArrayList<String>()
|
||||||
|
clouds.forEach {
|
||||||
|
// do parallax scrolling
|
||||||
|
it.posX += camDelta.x * cloudParallaxMultX
|
||||||
|
it.posY += camDelta.y * cloudParallaxMultY
|
||||||
|
|
||||||
|
|
||||||
|
it.update(windVector)
|
||||||
|
|
||||||
|
if (DEBUG_CAUSE_OF_DESPAWN && it.life == 0) {
|
||||||
|
immDespawnCount += 1
|
||||||
|
immDespawnCauses.add(it.despawnCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// printdbg(this, "Newborn cloud death rate: $immDespawnCount/$cloudsSpawned")
|
||||||
|
|
||||||
|
|
||||||
|
if (DEBUG_CAUSE_OF_DESPAWN && App.IS_DEVELOPMENT_BUILD && immDespawnCount > cloudsSpawned / 4) {
|
||||||
|
val despawnCauseStats = HashMap<String, Int>()
|
||||||
|
immDespawnCauses.forEach {
|
||||||
|
if (despawnCauseStats[it] != null) {
|
||||||
|
despawnCauseStats[it] = despawnCauseStats[it]!! + 1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
despawnCauseStats[it] = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
despawnCauseStats.forEach { s, i ->
|
||||||
|
printdbg(this, "Cause of death -- $s: $i")
|
||||||
|
}
|
||||||
|
System.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// remove clouds that are marked to be despawn
|
||||||
|
var i = 0
|
||||||
|
while (true) {
|
||||||
|
if (i >= clouds.size) break
|
||||||
|
|
||||||
|
if (clouds[i].flagToDespawn) {
|
||||||
|
clouds.removeAt(i)
|
||||||
|
i -= 1
|
||||||
|
cloudsSpawned -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cloudUpdateAkku += delta
|
||||||
|
|
||||||
|
|
||||||
|
oldCamPos.set(camvec)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val scrHscaler = App.scr.height / 720f
|
||||||
|
private val cloudSizeMult = App.scr.wf / TerrarumScreenSize.defaultW
|
||||||
|
|
||||||
|
private fun takeUniformRand(range: ClosedFloatingPointRange<Float>) =
|
||||||
|
FastMath.interpolateLinear(Math.random().toFloat(), range.start, range.endInclusive)
|
||||||
|
private fun takeTriangularRand(range: ClosedFloatingPointRange<Float>) =
|
||||||
|
FastMath.interpolateLinear((Math.random() + Math.random()).div(2f).toFloat(), range.start, range.endInclusive)
|
||||||
|
private fun takeGaussianRand(range: ClosedFloatingPointRange<Float>) =
|
||||||
|
FastMath.interpolateLinear((Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random()).div(8f).toFloat(), range.start, range.endInclusive)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns random point for clouds to spawn from, in the opposite side of the current wind vector
|
||||||
|
*/
|
||||||
|
private fun getCloudSpawningPosition(cloud: CloudProps, halfCloudSize: Float, windVector: Vector3): Vector3 {
|
||||||
|
val Z_LIM = ALPHA_ROLLOFF_Z/2f
|
||||||
|
val y = takeUniformRand(-cloud.altHigh..-cloud.altLow) * scrHscaler
|
||||||
|
|
||||||
|
var windVectorDir = toDegrees(atan2(windVector.z.toDouble(), windVector.x.toDouble())).toFloat() + 180f
|
||||||
|
if (windVectorDir < 0f) windVectorDir += 360f
|
||||||
|
windVectorDir /= 90f // full circle: 4
|
||||||
|
|
||||||
|
// an "edge" is a line of length 1 drawn into the edge of the square of size 1 (its total edge length will be 4)
|
||||||
|
// when the windVectorDir is not an integer, the "edge" will take the shape similar to this: ¬
|
||||||
|
// 'rr' is a point on the "edge", where 0.5 is a middle point in its length
|
||||||
|
// val rl = (windVectorDir % 1f).let { if (it < 0.5f) -it else it - 1f }.toInt()
|
||||||
|
// val rh = 1 + (windVectorDir % 1f).let { if (it < 0.5f) it else 1f - it }.toInt()
|
||||||
|
|
||||||
|
// choose between rl and rh using (windVectorDir % 1f) as a pivot
|
||||||
|
// if pivot = 0.3, rL is 70%, and rR is 30% likely
|
||||||
|
// plug the vote result into the when()
|
||||||
|
val selectedQuadrant = takeUniformRand(windVectorDir..windVectorDir + 1f)
|
||||||
|
|
||||||
|
// printdbg(this, "Dir: $windVectorDir, Rand(${windVectorDir}..${windVectorDir + 1f}) = ${selectedQuadrant.floorToInt()}($selectedQuadrant)")
|
||||||
|
|
||||||
|
val rr = takeUniformRand(0f..1f)
|
||||||
|
|
||||||
|
return when (selectedQuadrant.floorToInt()) {
|
||||||
|
-4, 0, 4 -> { // right side of the screen
|
||||||
|
val z = FastMath.interpolateLinear(rr, 1f, ALPHA_ROLLOFF_Z).pow(1.5f) // clouds are more likely to spawn with low Z-value
|
||||||
|
val posXscr = App.scr.width + halfCloudSize
|
||||||
|
val x = WeatherObjectCloud.screenXtoWorldX(posXscr, z)
|
||||||
|
Vector3(x, y, z)
|
||||||
|
}
|
||||||
|
-3, 1, 5 -> { // z = inf
|
||||||
|
val z = ALPHA_ROLLOFF_Z
|
||||||
|
val posXscr = FastMath.interpolateLinear(rr, App.scr.width + halfCloudSize, -halfCloudSize)
|
||||||
|
val x = WeatherObjectCloud.screenXtoWorldX(posXscr, Z_LIM)
|
||||||
|
Vector3(x, y, z)
|
||||||
|
}
|
||||||
|
-2, 2, 6 -> { // left side of the screen
|
||||||
|
val z = FastMath.interpolateLinear(rr, ALPHA_ROLLOFF_Z, 1f).pow(1.5f) // clouds are more likely to spawn with low Z-value
|
||||||
|
val posXscr = -halfCloudSize
|
||||||
|
val x = WeatherObjectCloud.screenXtoWorldX(posXscr, z)
|
||||||
|
Vector3(x, y, z)
|
||||||
|
}
|
||||||
|
-1, 3, 7 -> { // z = 0
|
||||||
|
val z = 0.1f
|
||||||
|
val posXscr = FastMath.interpolateLinear(rr, -halfCloudSize, App.scr.width + halfCloudSize)
|
||||||
|
val x = WeatherObjectCloud.screenXtoWorldX(posXscr, Z_LIM)
|
||||||
|
Vector3(x, y, z)
|
||||||
|
}
|
||||||
|
else -> throw InternalError()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun tryToSpawnCloud(currentWeather: BaseModularWeather, precalculatedPos: Vector3? = null) {
|
||||||
|
// printdbg(this, "Trying to spawn a cloud... (${cloudsSpawned} / ${cloudSpawnMax})")
|
||||||
|
|
||||||
|
if (cloudsSpawned < cloudSpawnMax) {
|
||||||
|
val flip = Math.random() < 0.5
|
||||||
|
val rC = takeUniformRand(0f..1f)
|
||||||
|
// val rZ = takeUniformRand(1f..ALPHA_ROLLOFF_Z/4f).pow(1.5f) // clouds are more likely to spawn with low Z-value
|
||||||
|
// val rY = takeUniformRand(-1f..1f)
|
||||||
|
val rT1 = takeTriangularRand(-1f..1f)
|
||||||
|
val (rA, rB) = doubleToLongBits(Math.random()).let {
|
||||||
|
it.ushr(20).and(0xFFFF).toInt() to it.ushr(36).and(0xFFFF).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
var cloudsToSpawn: CloudProps? = null
|
||||||
|
var c = 0
|
||||||
|
while (c < currentWeather.clouds.size) {
|
||||||
|
if (rC < currentWeather.clouds[c].probability) {
|
||||||
|
cloudsToSpawn = currentWeather.clouds[c]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cloudsToSpawn?.let { cloud ->
|
||||||
|
val cloudScale = cloud.getCloudScaleVariance(rT1)
|
||||||
|
val hCloudSize = (cloud.spriteSheet.tileW * cloudScale) / 2f + 1f
|
||||||
|
|
||||||
|
// val posXscr = initX ?: if (cloudDriftVector.x < 0) (App.scr.width + hCloudSize) else -hCloudSize
|
||||||
|
// val posX = WeatherObjectCloud.screenXtoWorldX(posXscr, rZ)
|
||||||
|
// val posY = randomPosWithin(-cloud.altHigh..-cloud.altLow, rY) * scrHscaler
|
||||||
|
|
||||||
|
val sheetX = rA % cloud.spriteSheet.horizontalCount
|
||||||
|
val sheetY = rB % cloud.spriteSheet.verticalCount
|
||||||
|
WeatherObjectCloud(cloud.spriteSheet.get(sheetX, sheetY), flip).also {
|
||||||
|
it.scale = cloudScale * cloudSizeMult
|
||||||
|
|
||||||
|
it.pos.set(precalculatedPos ?: getCloudSpawningPosition(cloud, hCloudSize, windVector))
|
||||||
|
|
||||||
|
// further set the random altitude if required
|
||||||
|
if (precalculatedPos != null) {
|
||||||
|
it.pos.y = takeUniformRand(-cloud.altHigh..-cloud.altLow) * scrHscaler
|
||||||
|
}
|
||||||
|
|
||||||
|
clouds.add(it)
|
||||||
|
cloudsSpawned += 1
|
||||||
|
|
||||||
|
|
||||||
|
// printdbg(this, "... Spawning ${cloud.category}($sheetX, $sheetY) cloud at pos ${it.pos}, scale ${it.scale}, invGamma ${it.darkness}")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initClouds() {
|
||||||
|
val hCloudSize = 1024f
|
||||||
|
// multiplier is an empirical value that depends on the 'rZ'
|
||||||
|
// it does converge at ~6, but having it as an initial state does not make it stay converged
|
||||||
|
repeat((currentWeather.cloudChance * 1.333f).ceilToInt()) {
|
||||||
|
|
||||||
|
val z = takeUniformRand(0.1f..ALPHA_ROLLOFF_Z / 4f - 0.1f).pow(1.5f) // clouds are more likely to spawn with low Z-value
|
||||||
|
|
||||||
|
val zz = FastMath.interpolateLinear((z / ALPHA_ROLLOFF_Z) * 0.8f + 0.1f, ALPHA_ROLLOFF_Z / 4f, ALPHA_ROLLOFF_Z)
|
||||||
|
|
||||||
|
val x = WeatherObjectCloud.screenXtoWorldX(takeUniformRand(0f..App.scr.wf), zz)
|
||||||
|
|
||||||
|
|
||||||
|
tryToSpawnCloud(currentWeather, Vector3(x, 0f, z))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun titleScreenInitWeather() {
|
||||||
|
currentWeather = weatherList["titlescreen"]!![0]
|
||||||
|
currentWeather.forceWindVec = Vector3(-0.98f, 0f, -0.21f)
|
||||||
|
initClouds()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> Array<T?>.addAtFreeSpot(obj: T) {
|
||||||
|
var c = 0
|
||||||
|
while (true) {
|
||||||
|
if (this[c] == null) break
|
||||||
|
c += 1
|
||||||
|
}
|
||||||
|
this[c] = obj
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var turbidity = 1.0; private set
|
var turbidity = 1.0; private set
|
||||||
private var gH = 1.8f * App.scr.height
|
private var gH = 1.8f * App.scr.height
|
||||||
// private var gH = 0.8f * App.scr.height
|
// private var gH = 0.8f * App.scr.height
|
||||||
@@ -166,6 +528,21 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
*/
|
*/
|
||||||
internal fun render(camera: Camera, batch: FlippingSpriteBatch, world: GameWorld) {
|
internal fun render(camera: Camera, batch: FlippingSpriteBatch, world: GameWorld) {
|
||||||
drawSkybox(camera, batch, world)
|
drawSkybox(camera, batch, world)
|
||||||
|
drawClouds(batch)
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun drawClouds(batch: SpriteBatch) {
|
||||||
|
batch.inUse { _ ->
|
||||||
|
batch.shader = shaderClouds
|
||||||
|
batch.shader.setUniformf("gamma", currentWeather.cloudGamma)
|
||||||
|
batch.shader.setUniformf("shadeCol", 0.06f, 0.07f, 0.08f, 1f) // TODO temporary value
|
||||||
|
|
||||||
|
clouds.forEach {
|
||||||
|
batch.color = Color(globalLightNow.r, globalLightNow.g, globalLightNow.b, it.alpha)
|
||||||
|
it.render(batch, 0f, 0f)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val parallaxDomainSize = 400f
|
private val parallaxDomainSize = 400f
|
||||||
@@ -223,20 +600,20 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
val astrumY = ((world.worldTime.TIME_T / WorldTime.DIURNAL_MOTION_LENGTH) % 1f) * starmapTex.regionHeight
|
val astrumY = ((world.worldTime.TIME_T / WorldTime.DIURNAL_MOTION_LENGTH) % 1f) * starmapTex.regionHeight
|
||||||
|
|
||||||
batch.inUse {
|
batch.inUse {
|
||||||
batch.shader = shaderBlendMax
|
batch.shader = shaderAstrum
|
||||||
shaderBlendMax.setUniformi("tex1", 1)
|
shaderAstrum.setUniformi("tex1", 1)
|
||||||
shaderBlendMax.setUniformf("drawOffsetSize", 0f, gradY, App.scr.wf, gH)
|
shaderAstrum.setUniformf("drawOffsetSize", 0f, gradY, App.scr.wf, gH)
|
||||||
shaderBlendMax.setUniform4fv("uvA", uvs, 0, 4)
|
shaderAstrum.setUniform4fv("uvA", uvs, 0, 4)
|
||||||
shaderBlendMax.setUniform4fv("uvB", uvs, 4, 4)
|
shaderAstrum.setUniform4fv("uvB", uvs, 4, 4)
|
||||||
shaderBlendMax.setUniform4fv("uvC", uvs, 8, 4)
|
shaderAstrum.setUniform4fv("uvC", uvs, 8, 4)
|
||||||
shaderBlendMax.setUniform4fv("uvD", uvs, 12, 4)
|
shaderAstrum.setUniform4fv("uvD", uvs, 12, 4)
|
||||||
shaderBlendMax.setUniform4fv("uvE", uvs, 16, 4)
|
shaderAstrum.setUniform4fv("uvE", uvs, 16, 4)
|
||||||
shaderBlendMax.setUniform4fv("uvF", uvs, 20, 4)
|
shaderAstrum.setUniform4fv("uvF", uvs, 20, 4)
|
||||||
shaderBlendMax.setUniform4fv("uvG", uvs, 24, 4)
|
shaderAstrum.setUniform4fv("uvG", uvs, 24, 4)
|
||||||
shaderBlendMax.setUniform4fv("uvH", uvs, 28, 4)
|
shaderAstrum.setUniform4fv("uvH", uvs, 28, 4)
|
||||||
shaderBlendMax.setUniformf("texBlend", mornNoonBlend, turbX, albX, 0f)
|
shaderAstrum.setUniformf("texBlend", mornNoonBlend, turbX, albX, 0f)
|
||||||
shaderBlendMax.setUniformf("astrumScroll", astrumOffX + astrumX, astrumOffY + astrumY)
|
shaderAstrum.setUniformf("astrumScroll", astrumOffX + astrumX, astrumOffY + astrumY)
|
||||||
shaderBlendMax.setUniformf("randomNumber",
|
shaderAstrum.setUniformf("randomNumber",
|
||||||
// (world.worldTime.TIME_T.plus(31L) xor 1453L + 31L).and(1023).toFloat(),
|
// (world.worldTime.TIME_T.plus(31L) xor 1453L + 31L).and(1023).toFloat(),
|
||||||
// (world.worldTime.TIME_T.plus(37L) xor 862L + 31L).and(1023).toFloat(),
|
// (world.worldTime.TIME_T.plus(37L) xor 862L + 31L).and(1023).toFloat(),
|
||||||
// (world.worldTime.TIME_T.plus(23L) xor 1639L + 29L).and(1023).toFloat(),
|
// (world.worldTime.TIME_T.plus(23L) xor 1639L + 29L).and(1023).toFloat(),
|
||||||
@@ -366,20 +743,36 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
val skyboxInJson = JSON.getString("skyboxGradColourMap")
|
val skyboxInJson = JSON.getString("skyboxGradColourMap")
|
||||||
val lightbox = JSON.getString("daylightClut")
|
val lightbox = JSON.getString("daylightClut")
|
||||||
val extraImagesPath = JSON.get("extraImages").asStringArray()
|
|
||||||
|
|
||||||
val skybox = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${skyboxInJson}"))
|
val skybox = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${skyboxInJson}"))
|
||||||
val daylight = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${lightbox}"))
|
val daylight = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${lightbox}"))
|
||||||
|
|
||||||
|
|
||||||
val extraImages = ArrayList<Texture>()
|
|
||||||
for (i in extraImagesPath)
|
|
||||||
extraImages.add(Texture(ModMgr.getGdxFile(modname, "$pathToImage/${i}")))
|
|
||||||
|
|
||||||
|
|
||||||
val classification = JSON.getString("classification")
|
val classification = JSON.getString("classification")
|
||||||
|
|
||||||
|
|
||||||
|
val cloudsMap = ArrayList<CloudProps>()
|
||||||
|
val clouds = JSON["clouds"]
|
||||||
|
clouds.forEachSiblings { name, json ->
|
||||||
|
cloudsMap.add(CloudProps(
|
||||||
|
name,
|
||||||
|
TextureRegionPack(ModMgr.getGdxFile(modname, "$pathToImage/${json.getString("filename")}"), json.getInt("tw"), json.getInt("th")),
|
||||||
|
json.getFloat("probability"),
|
||||||
|
json.getFloat("baseScale"),
|
||||||
|
json.getFloat("scaleVariance"),
|
||||||
|
json.getFloat("altLow"),
|
||||||
|
json.getFloat("altHigh"),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
cloudsMap.sortBy { it.probability }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var mixFrom: String?
|
var mixFrom: String?
|
||||||
try { mixFrom = JSON.getString("mixFrom") }
|
try { mixFrom = JSON.getString("mixFrom") }
|
||||||
@@ -394,20 +787,28 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
|
|
||||||
return BaseModularWeather(
|
return BaseModularWeather(
|
||||||
|
json = JSON,
|
||||||
skyboxGradColourMap = skybox,
|
skyboxGradColourMap = skybox,
|
||||||
daylightClut = daylight,
|
daylightClut = daylight,
|
||||||
classification = classification,
|
classification = classification,
|
||||||
extraImages = extraImages
|
cloudChance = JSON.getFloat("cloudChance"),
|
||||||
|
windSpeed = JSON.getFloat("windSpeed"),
|
||||||
|
windSpeedVariance = JSON.getFloat("windSpeedVariance"),
|
||||||
|
cloudGamma = JSON["cloudGamma"].asFloatArray().let { Vector2(it[0], it[1]) },
|
||||||
|
cloudGammaVariance = JSON["cloudGammaVariance"].asFloatArray().let { Vector2(it[0], it[1]) },
|
||||||
|
clouds = cloudsMap,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dispose() {
|
fun dispose() {
|
||||||
weatherList.values.forEach { list ->
|
weatherList.values.forEach { list ->
|
||||||
list.forEach { weather ->
|
list.forEach { weather ->
|
||||||
weather.extraImages.forEach { it.tryDispose() }
|
weather.clouds.forEach { it.spriteSheet.dispose() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
starmapTex.texture.dispose()
|
starmapTex.texture.dispose()
|
||||||
shaderBlendMax.dispose()
|
shaderAstrum.dispose()
|
||||||
|
shaderClouds.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
33
src/net/torvald/terrarum/weather/WeatherObject.kt
Normal file
33
src/net/torvald/terrarum/weather/WeatherObject.kt
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package net.torvald.terrarum.weather
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import com.badlogic.gdx.math.Vector3
|
||||||
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-21.
|
||||||
|
*/
|
||||||
|
abstract class WeatherObject : Disposable {
|
||||||
|
|
||||||
|
/** vec3(posX, posY, scale) */
|
||||||
|
var pos: Vector3 = Vector3(0f, 0f, 1f)
|
||||||
|
|
||||||
|
var posX: Float
|
||||||
|
get() = pos.x
|
||||||
|
set(value) { pos.x = value }
|
||||||
|
var posY: Float
|
||||||
|
get() = pos.y
|
||||||
|
set(value) { pos.y = value }
|
||||||
|
var posZ: Float
|
||||||
|
get() = pos.z
|
||||||
|
set(value) { pos.z = value }
|
||||||
|
var scale: Float = 1f
|
||||||
|
|
||||||
|
var alpha: Float = 1f
|
||||||
|
|
||||||
|
var flagToDespawn = false
|
||||||
|
|
||||||
|
abstract fun update()
|
||||||
|
abstract fun render(batch: SpriteBatch, offsetX: Float, offsetY: Float)
|
||||||
|
|
||||||
|
}
|
||||||
137
src/net/torvald/terrarum/weather/WeatherObjectCloud.kt
Normal file
137
src/net/torvald/terrarum/weather/WeatherObjectCloud.kt
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
package net.torvald.terrarum.weather
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
import com.badlogic.gdx.math.Vector3
|
||||||
|
import com.jme3.math.FastMath
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
|
import kotlin.math.pow
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
import kotlin.math.sign
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-21.
|
||||||
|
*/
|
||||||
|
class WeatherObjectCloud(private val texture: TextureRegion, private val flipW: Boolean) : WeatherObject(), Comparable<WeatherObjectCloud> {
|
||||||
|
|
||||||
|
override fun update() {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
var life = 0; private set
|
||||||
|
var despawnCode = ""; private set
|
||||||
|
|
||||||
|
private val lifespan = 40000 + ((Math.random() + Math.random()) * 20000).roundToInt() // triangular distibution of 40000..80000
|
||||||
|
|
||||||
|
private fun getZflowMult(z: Float) = z / ((z / 4f).pow(1.5f))
|
||||||
|
|
||||||
|
private var eigenAlpha = 0f
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FlowVector: In which direction the cloud flows. Vec3(dX, dY, dScale)
|
||||||
|
* Resulting vector: (x + dX, y + dY, scale * dScale)
|
||||||
|
*/
|
||||||
|
fun update(flowVector: Vector3) {
|
||||||
|
pos.add(
|
||||||
|
flowVector.cpy().
|
||||||
|
scl(1f, 1f, getZflowMult(posZ)). // this will break the perspective if flowVector.z.abs() is close to 1, but it has to be here to "keep the distance"
|
||||||
|
scl(vecMult)
|
||||||
|
)
|
||||||
|
|
||||||
|
eigenAlpha = if (posZ < 1f) posZ.pow(0.5f) else -((posZ - 1f) / ALPHA_ROLLOFF_Z) + 1f
|
||||||
|
|
||||||
|
alpha = eigenAlpha * if (life < lifespan) 1f else 1f - (life - lifespan) / OLD_AGE_DECAY
|
||||||
|
|
||||||
|
|
||||||
|
val lrCoord = screenCoordBottomLRforDespawnCalculation
|
||||||
|
if (lrCoord.x > WeatherMixer.oobMarginR || lrCoord.z < WeatherMixer.oobMarginL || posZ !in 0.0001f..ALPHA_ROLLOFF_Z + 1f || alpha < 0f) {
|
||||||
|
flagToDespawn = true
|
||||||
|
|
||||||
|
despawnCode = if (lrCoord.x > WeatherMixer.oobMarginR) "OUT_OF_SCREEN_RIGHT"
|
||||||
|
else if (lrCoord.z < WeatherMixer.oobMarginL) "OUT_OF_SCREEN_LEFT"
|
||||||
|
else if (posZ < 0.0001f) "OUT_OF_SCREEN_TOO_CLOSE"
|
||||||
|
else if (posZ > ALPHA_ROLLOFF_Z + 1f) "OUT_OF_SCREEN_TOO_FAR"
|
||||||
|
else if (life >= lifespan + OLD_AGE_DECAY) "OLD_AGE"
|
||||||
|
else if (alpha < 0f) "ALPHA_BELOW_ZERO"
|
||||||
|
else "UNKNOWN"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
life += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val w = App.scr.halfwf
|
||||||
|
private val h = App.scr.hf * 0.5f
|
||||||
|
private val vecMult = Vector3(1f, 1f, 1f / (4f * h))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X/Y position is a bottom-centre point of the image
|
||||||
|
* Shader must be prepared prior to the render() call
|
||||||
|
*/
|
||||||
|
override fun render(batch: SpriteBatch, offsetX: Float, offsetY: Float) {
|
||||||
|
val sc = screenCoord
|
||||||
|
|
||||||
|
if (flipW)
|
||||||
|
batch.draw(texture, sc.x + texture.regionWidth / posZ, sc.y, -texture.regionWidth * sc.z, texture.regionHeight * sc.z)
|
||||||
|
else
|
||||||
|
batch.draw(texture, sc.x, sc.y, texture.regionWidth * sc.z, texture.regionHeight * sc.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vec3(screen X, screenY, draw scale)
|
||||||
|
*/
|
||||||
|
val screenCoord: Vector3
|
||||||
|
get() {
|
||||||
|
val x = posX - texture.regionWidth * scale * 0.5f
|
||||||
|
val y = posY - texture.regionHeight * scale
|
||||||
|
val z = posZ // must be at least 1.0
|
||||||
|
|
||||||
|
val drawX = (x + w * (z-1)) / z
|
||||||
|
val drawY = (y + h * (z-1)) / z
|
||||||
|
val drawScale = scale / z
|
||||||
|
|
||||||
|
return Vector3(drawX, drawY, drawScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vec3(screen-X of bottom-left point, screen-Y, screen-X of bottom-right point)
|
||||||
|
*/
|
||||||
|
val screenCoordBottomLR: Vector3
|
||||||
|
get() {
|
||||||
|
val xL = posX - texture.regionWidth * scale * 0.5f
|
||||||
|
val xR = posX + texture.regionWidth * scale * 0.5f
|
||||||
|
val y = posY - texture.regionHeight * scale
|
||||||
|
val z = posZ // must be larger than 0
|
||||||
|
|
||||||
|
val drawXL = (xL + w * (z-1)) / z
|
||||||
|
val drawXR = (xR + w * (z-1)) / z
|
||||||
|
val drawY = (y + h * (z-1)) / z
|
||||||
|
|
||||||
|
return Vector3(drawXL, drawY, drawXR)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val screenCoordBottomLRforDespawnCalculation: Vector3
|
||||||
|
get() {
|
||||||
|
val xL = posX - texture.regionWidth * scale * 0.5f
|
||||||
|
val xR = posX + texture.regionWidth * scale * 0.5f
|
||||||
|
val y = posY - texture.regionHeight * scale
|
||||||
|
val z = FastMath.interpolateLinear(posZ / ALPHA_ROLLOFF_Z, ALPHA_ROLLOFF_Z / 4f, ALPHA_ROLLOFF_Z)
|
||||||
|
|
||||||
|
val drawXL = (xL + w * (z-1)) / z
|
||||||
|
val drawXR = (xR + w * (z-1)) / z
|
||||||
|
val drawY = (y + h * (z-1)) / z
|
||||||
|
|
||||||
|
return Vector3(drawXL, drawY, drawXR)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() { /* cloud texture will be disposed of by the WeatherMixer */ }
|
||||||
|
override fun compareTo(other: WeatherObjectCloud): Int = (other.posZ - this.posZ).sign.toInt()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun screenXtoWorldX(screenX: Float, z: Float) = screenX * z - App.scr.halfwf * (z - 1f)
|
||||||
|
const val ALPHA_ROLLOFF_Z = 64f
|
||||||
|
const val OLD_AGE_DECAY = 4000f
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,6 +70,9 @@ object WorldCamera {
|
|||||||
var worldHeight = 0
|
var worldHeight = 0
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
inline val camVector: com.badlogic.gdx.math.Vector2
|
||||||
|
get() = com.badlogic.gdx.math.Vector2(gdxCamX, gdxCamY)
|
||||||
|
|
||||||
fun update(world: GameWorld, player: ActorWithBody?) {
|
fun update(world: GameWorld, player: ActorWithBody?) {
|
||||||
if (player == null) return
|
if (player == null) return
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#version 150
|
#version 400
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
@@ -16,5 +16,6 @@ const vec2 boolean = vec2(0.0, 1.0);
|
|||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 colorTex0 = texture(u_texture, v_texCoords); // lightmap (RGB) pre-mixed
|
vec4 colorTex0 = texture(u_texture, v_texCoords); // lightmap (RGB) pre-mixed
|
||||||
vec4 colorTex1 = texture(tex1, v_texCoords); // lightmap (A) pre-mixed
|
vec4 colorTex1 = texture(tex1, v_texCoords); // lightmap (A) pre-mixed
|
||||||
fragColor = (max(colorTex0, colorTex1) * boolean.yyyx) + (colorTex0 * boolean.xxxy);
|
// fragColor = (max(colorTex0, colorTex1) * boolean.yyyx) + (colorTex0 * boolean.xxxy);
|
||||||
|
fragColor = fma(max(colorTex0, colorTex1), boolean.yyyx, colorTex0 * boolean.xxxy);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#version 150
|
#version 400
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
@@ -150,7 +150,10 @@ void main(void) {
|
|||||||
); // c = c0..c1
|
); // c = c0..c1
|
||||||
|
|
||||||
|
|
||||||
fragColor = (max(colorTex0, colorTex1) * boolean.yyyx) + boolean.xxxy;
|
// fragColor = (max(colorTex0, colorTex1) * boolean.yyyx) + boolean.xxxy;
|
||||||
|
fragColor = fma(max(colorTex0, colorTex1), boolean.yyyx, boolean.xxxy);
|
||||||
|
|
||||||
|
|
||||||
// fragColor = colorTex1;
|
// fragColor = colorTex1;
|
||||||
// fragColor = randomness * boolean.yyyx + boolean.xxxy;
|
// fragColor = randomness * boolean.yyyx + boolean.xxxy;
|
||||||
// fragColor = (randomness.rrrr + (colorTex1 * vec4(2.0, -2.0, 2.0, 1.0))) * boolean.yyyx + boolean.xxxy;
|
// fragColor = (randomness.rrrr + (colorTex1 * vec4(2.0, -2.0, 2.0, 1.0))) * boolean.yyyx + boolean.xxxy;
|
||||||
|
|||||||
30
src/shaders/clouds.frag
Normal file
30
src/shaders/clouds.frag
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#version 400
|
||||||
|
|
||||||
|
#ifdef GL_ES
|
||||||
|
#define LOWP lowp
|
||||||
|
precision mediump float;
|
||||||
|
#else
|
||||||
|
#define LOWP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
in LOWP vec4 v_color; // lightCol.rgb + cloud's alpha
|
||||||
|
in vec2 v_texCoords;
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
const vec2 boolean = vec2(0.0, 1.0);
|
||||||
|
|
||||||
|
uniform vec2 gamma = vec2(10, 2.0); // vec2(gamma for RGB, gamma for A)
|
||||||
|
|
||||||
|
uniform LOWP vec4 shadeCol;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// r: bw diffuse map, g: normal, b: normal, a: bw diffuse alpha
|
||||||
|
vec4 inCol = texture(u_texture, v_texCoords);
|
||||||
|
vec4 rawCol = pow(inCol, gamma.xxxy);
|
||||||
|
|
||||||
|
// do gradient mapping here
|
||||||
|
vec4 outCol = fma(mix(shadeCol, v_color, rawCol.r), boolean.yyyx, rawCol * boolean.xxxy);
|
||||||
|
|
||||||
|
fragColor = outCol * fma(v_color, boolean.xxxy, boolean.yyyx);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#version 150
|
#version 400
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
@@ -41,7 +41,8 @@ vec4 getDitherredDot(vec4 inColor) {
|
|||||||
|
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
float scale = v_texCoords.y * (1.0 - parallax_size) + (parallax_size / 2.0) + (parallax * parallax_size / 2.0);
|
float parallaxAdder = 0.5 * (parallax + 1.0) * parallax_size;
|
||||||
|
float scale = fma(v_texCoords.y, 1.0 - parallax_size, parallaxAdder);
|
||||||
|
|
||||||
float zoomSamplePoint = (1.0 - zoomInv) / 2.0;// will never quite exceed 0.5
|
float zoomSamplePoint = (1.0 - zoomInv) / 2.0;// will never quite exceed 0.5
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#version 150
|
#version 400
|
||||||
in vec4 v_color;
|
in vec4 v_color;
|
||||||
in vec2 v_texCoords;
|
in vec2 v_texCoords;
|
||||||
uniform sampler2D u_texture;
|
uniform sampler2D u_texture;
|
||||||
@@ -11,5 +11,6 @@ void main(void) {
|
|||||||
vec4 incolour = texture(u_texture, v_texCoords);
|
vec4 incolour = texture(u_texture, v_texCoords);
|
||||||
float lum = dot(incolour * desaturate, boolean.yyyx) * 0.5 + 0.5;
|
float lum = dot(incolour * desaturate, boolean.yyyx) * 0.5 + 0.5;
|
||||||
|
|
||||||
fragColor = v_color * (vec4(lum) * boolean.yyyx + incolour * boolean.xxxy);
|
// fragColor = v_color * (vec4(lum) * boolean.yyyx + incolour * boolean.xxxy);
|
||||||
|
fragColor = v_color * fma(vec4(lum), boolean.yyyx, incolour * boolean.xxxy);
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
* http://momentsingraphics.de/BlueNoise.html
|
* http://momentsingraphics.de/BlueNoise.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#version 150
|
#version 400
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
@@ -79,7 +79,7 @@ void main(void) {
|
|||||||
// Dither the output
|
// Dither the output
|
||||||
vec4 graded = ycocg_to_rgb * newColour;
|
vec4 graded = ycocg_to_rgb * newColour;
|
||||||
vec4 selvec = getDitherredDot(graded);
|
vec4 selvec = getDitherredDot(graded);
|
||||||
vec4 outcol = selvec * boolean.yyyx + boolean.xxxy; // use quantised RGB but not the A
|
vec4 outcol = fma(selvec, boolean.yyyx, boolean.xxxy); // use quantised RGB but not the A
|
||||||
|
|
||||||
fragColor = outcol;
|
fragColor = outcol;
|
||||||
// ivec4 bytes = ivec4(255.0 * outcol);
|
// ivec4 bytes = ivec4(255.0 * outcol);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* http://momentsingraphics.de/BlueNoise.html
|
* http://momentsingraphics.de/BlueNoise.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#version 150
|
#version 400
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
@@ -60,5 +60,5 @@ void main(void) {
|
|||||||
|
|
||||||
// Dither the output
|
// Dither the output
|
||||||
vec4 graded = ycocg_to_rgb * newColour;
|
vec4 graded = ycocg_to_rgb * newColour;
|
||||||
fragColor = graded * boolean.yyyx + boolean.xxxy; // use quantised RGB but not the A
|
fragColor = fma(graded, boolean.yyyx, boolean.xxxy); // use quantised RGB but not the A
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#version 150
|
#version 400
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
@@ -107,7 +107,7 @@ void main() {
|
|||||||
|
|
||||||
vec4 finalBreakage = drawBreakage * texture(tilesAtlas, finalUVCoordForBreakage); // drawBreakeage = 0 to not draw, = 1 to draw
|
vec4 finalBreakage = drawBreakage * texture(tilesAtlas, finalUVCoordForBreakage); // drawBreakeage = 0 to not draw, = 1 to draw
|
||||||
|
|
||||||
vec4 finalColor =mix(finalTile, finalBreakage, finalBreakage.a) * bc.xxxy + (finalTile * bc.yyyx);
|
vec4 finalColor = fma(mix(finalTile, finalBreakage, finalBreakage.a), bc.xxxy, finalTile * bc.yyyx);
|
||||||
|
|
||||||
fragColor = mix(colourFilter, colourFilter * finalColor, mulBlendIntensity);
|
fragColor = mix(colourFilter, colourFilter * finalColor, mulBlendIntensity);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#version 150
|
#version 400
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
@@ -121,5 +121,5 @@ void main() {
|
|||||||
vec2 entry = mod(gl_FragCoord.xy, vec2(bayerSize, bayerSize));
|
vec2 entry = mod(gl_FragCoord.xy, vec2(bayerSize, bayerSize));
|
||||||
float bayerThreshold = float(bayer[int(entry.y) * int(bayerSize) + int(entry.x)]) / bayerDivider;
|
float bayerThreshold = float(bayer[int(entry.y) * int(bayerSize) + int(entry.x)]) / bayerDivider;
|
||||||
|
|
||||||
fragColor = undithered * bc.xxxy + vec4((undithered.a > bayerThreshold) ? 1.0 : 0.0) * bc.yyyx;
|
fragColor = fma(undithered, bc.xxxy, vec4((undithered.a > bayerThreshold) ? 1.0 : 0.0) * bc.yyyx);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user