Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
061bd8df9a | ||
|
|
9c8c87aec0 | ||
|
|
eedfce0c3a | ||
|
|
04c786c254 | ||
|
|
8566c44761 | ||
|
|
67e862d81e | ||
|
|
f26c385a1f | ||
|
|
3d29a7cadb | ||
|
|
de06052e87 | ||
|
|
547b1d4959 | ||
|
|
db8048a1b6 | ||
|
|
6676c3a9a9 | ||
|
|
e2918de5aa | ||
|
|
c2fb43b761 | ||
|
|
6cfffc5daa | ||
|
|
b5e7227fba | ||
|
|
dbebf0f615 | ||
|
|
2377d42c58 | ||
|
|
7607e92fea | ||
|
|
fdc6ffdd39 | ||
|
|
efca8dab86 | ||
|
|
39377abc12 | ||
|
|
3d00e7a360 | ||
|
|
04d5e418bf | ||
|
|
cc606585ad | ||
|
|
6d1235ca18 | ||
|
|
fe0a4d80bf | ||
|
|
8ef5c055b0 | ||
|
|
6be9c07ce4 | ||
|
|
adc454cfc9 | ||
|
|
2cdecbf069 | ||
|
|
d74c95f088 | ||
|
|
9d5dbbd2f5 | ||
|
|
3a2bf1f4f8 | ||
|
|
d49eeccd3f | ||
|
|
7e13db2271 | ||
|
|
389d15bda0 | ||
|
|
4ae696550f | ||
|
|
e92dc8108d | ||
|
|
ce784e0c66 | ||
|
|
55b52aec89 | ||
|
|
c415e8a762 | ||
|
|
1d6e973ab8 | ||
|
|
e2a17164ca | ||
|
|
0d24192a23 | ||
|
|
e5814ae449 | ||
|
|
e869269ab6 | ||
|
|
c80f5ae218 | ||
|
|
bd90908a72 | ||
|
|
21860eefba | ||
|
|
6297f569a2 | ||
|
|
e5dfe2162a | ||
|
|
92dfd34610 | ||
|
|
dea884f9c2 | ||
|
|
2d3ee9d7ef | ||
|
|
2b80362795 | ||
|
|
9c10e5bfe1 | ||
|
|
b524e47aa8 | ||
|
|
9a8927755c | ||
|
|
f6d492dbb4 | ||
|
|
a8d445f56c | ||
|
|
515a26c926 | ||
|
|
64d6abf771 | ||
|
|
950b8ed68b | ||
|
|
c703484705 | ||
|
|
4d300f6aed | ||
|
|
b9efd702dc | ||
|
|
93cee47a13 | ||
|
|
627ac3c0ba | ||
|
|
d178d86b4d | ||
|
|
c8c0157d79 | ||
|
|
c6c60fc163 | ||
|
|
20c4ed3274 | ||
|
|
1610735fcd | ||
|
|
139a42ba8b | ||
|
|
9477cb6d1e | ||
|
|
60f42e7cdf | ||
|
|
79cd63b8bc | ||
|
|
a2fb9bc76e | ||
|
|
1acc70eb43 | ||
|
|
633169ea0f | ||
|
|
69ea634469 | ||
|
|
6020c75004 | ||
|
|
f34a261c77 | ||
|
|
6ee08b4a5a | ||
|
|
91426ff30e | ||
|
|
1215645c4e | ||
|
|
dd0f9c629b | ||
|
|
1636336f99 | ||
|
|
50a11a1107 | ||
|
|
4eee03985c | ||
|
|
ca1ed5fac5 | ||
|
|
7eb057384c | ||
|
|
9976e2053c | ||
|
|
1875af1a00 | ||
|
|
b9fc2c5539 | ||
|
|
cee8d447f8 | ||
|
|
04880cebe6 | ||
|
|
c3f0df9033 | ||
|
|
ad1ec8e4f6 | ||
|
|
ff66433c34 | ||
|
|
61f922fbd5 | ||
|
|
511e971adc | ||
|
|
211512aee8 | ||
|
|
edc5f94957 | ||
|
|
761704ce11 | ||
|
|
74d6a69a0e | ||
|
|
5edd79feaa | ||
|
|
c5121f0f10 | ||
|
|
c2414d0c5d | ||
|
|
0b5a2c1e4f | ||
|
|
18a2d812a7 | ||
|
|
510bb6f135 | ||
|
|
d84e8fa460 | ||
|
|
098efef8e2 | ||
|
|
daf537e0d4 | ||
|
|
260051a190 | ||
|
|
66dafd2bb6 | ||
|
|
ada4756065 | ||
|
|
2fe3429a9a | ||
|
|
3db7aa7cac | ||
|
|
5e6181b8f3 | ||
|
|
08f7f87f23 | ||
|
|
5b4984aa32 | ||
|
|
8396106b2e | ||
|
|
d1d212ef32 | ||
|
|
f6eff6b43a | ||
|
|
7abf696d29 | ||
|
|
a94ef019be | ||
|
|
1c9ebb2318 | ||
|
|
e64dc6ad91 | ||
|
|
50295a160c | ||
|
|
308bf3dae0 | ||
|
|
470f9d01e0 | ||
|
|
8559f9ccd2 | ||
|
|
e1cd3420ce | ||
|
|
21d6f5610b | ||
|
|
0660817c30 | ||
|
|
16341f4d04 | ||
|
|
50901bae92 | ||
|
|
c23c0056a1 | ||
|
|
76c3d4d262 | ||
|
|
c024816c37 | ||
|
|
c9246a4fc5 | ||
|
|
282992c1ec | ||
|
|
eee2cd0db1 | ||
|
|
448ba30415 | ||
|
|
b82eeb4f95 | ||
|
|
4f311197bd | ||
|
|
49c2e8c55f | ||
|
|
447514aa1d | ||
|
|
c5897ab467 | ||
|
|
d87da7928c | ||
|
|
481afc2e7b | ||
|
|
0deeb5cb29 | ||
|
|
b05af110f7 | ||
|
|
6e45279301 | ||
|
|
d3adab07d4 | ||
|
|
d0dcb33382 | ||
|
|
3bca3ed851 | ||
|
|
24c8f66b32 | ||
|
|
2982b03bdf | ||
|
|
c391c8971c | ||
|
|
c73a1df2a5 | ||
|
|
0f4cd026d3 | ||
|
|
5a589fb0f0 | ||
|
|
652accb89b | ||
|
|
93e3025e31 | ||
|
|
a9ce60dde5 | ||
|
|
4cada3276c | ||
|
|
8d38384310 | ||
|
|
92886cd964 | ||
|
|
b768990c0c | ||
|
|
938365b9e8 | ||
|
|
89fe5eb063 | ||
|
|
56728e147f | ||
|
|
382cf33dd9 | ||
|
|
01ef7b1657 | ||
|
|
630258d2a0 | ||
|
|
9f376f7061 | ||
|
|
4a70193562 | ||
|
|
e2482f0e1d | ||
|
|
0d6aaca77d | ||
|
|
f2be6f018c | ||
|
|
5d5f14b7c5 | ||
|
|
d2efe0374c | ||
|
|
278db50cfd | ||
|
|
12dbbe2251 | ||
|
|
134b443675 | ||
|
|
7903537503 | ||
|
|
0c989e88e1 | ||
|
|
0e5d9f1d12 | ||
|
|
327a39bc56 | ||
|
|
0e687efd6e | ||
|
|
8a2a85a683 | ||
|
|
3319947bdf | ||
|
|
3a6e1aabe2 | ||
|
|
db07aba271 | ||
|
|
75bb6a09ff | ||
|
|
a9a14c810e | ||
|
|
9c1aca3474 | ||
|
|
a62af71cef | ||
|
|
0b38e07d1d | ||
|
|
7df5c204c4 | ||
|
|
2d9576f84d | ||
|
|
3e7da21a05 | ||
|
|
92dd7886f0 | ||
|
|
8c154acd4a | ||
|
|
8ff04112a2 | ||
|
|
d595ebdd5e | ||
|
|
bf28b98a03 | ||
|
|
779fb404f5 | ||
|
|
196f313399 | ||
|
|
6fea5b936a | ||
|
|
fd04e8e867 | ||
|
|
687f1bfd12 | ||
|
|
3b735090e4 | ||
|
|
dde35f2b2e | ||
|
|
704c3906e6 | ||
|
|
0413376752 | ||
|
|
c26fb23197 | ||
|
|
50db6475fe | ||
|
|
a84771f764 | ||
|
|
58ac340c1c | ||
|
|
d2612fd508 | ||
|
|
a01f9d5883 | ||
|
|
562175df6c | ||
|
|
13f692f8f0 | ||
|
|
bc16f9aedc | ||
|
|
3eb0cdc6f5 | ||
|
|
fb354374e3 | ||
|
|
644f4d80f7 | ||
|
|
8125ddb602 | ||
|
|
1a26268488 | ||
|
|
53c6cd4fa5 | ||
|
|
7bd4244e2f | ||
|
|
1788fb7b84 | ||
|
|
c9592a87f6 | ||
|
|
3b34446f84 | ||
|
|
7fe4eb3931 | ||
|
|
44e8e374b9 | ||
|
|
218b421e16 | ||
|
|
f4d97fff39 | ||
|
|
d1b447525a |
No files matched your search
@@ -80,21 +80,24 @@ jobs:
|
||||
rustup toolchain install stable --profile minimal --component rustfmt --component clippy
|
||||
rustup default stable
|
||||
echo "WGPU_BACKEND=dx12" >> "$GITHUB_ENV"
|
||||
# On a pull request, the next three checks compare with HEAD^1: the main that GitHub's merge commit puts the pull
|
||||
# request on. pull_request.base.sha is main at the pull request's last push and falls behind, so main's own
|
||||
# changes since then would count as the pull request's (#13874).
|
||||
# docs/layers.md: a crate depends only on its own layer or a lower one; today's exceptions only shrink.
|
||||
- name: Crates follow the layers
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
run: python3 tools/check_layers.py ${BASE_SHA:+--base "$BASE_SHA"}
|
||||
BASE: ${{ github.event_name == 'pull_request' && 'HEAD^1' || '' }}
|
||||
run: python3 tools/check_layers.py ${BASE:+--base "$BASE"}
|
||||
# docs/layers.md#built-in-addresses: every built-in outside address in the Horizon layer's home; the rest only shrinks.
|
||||
- name: Built-in addresses stay in their home
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
run: python3 tools/check_addresses.py ${BASE_SHA:+--base "$BASE_SHA"}
|
||||
BASE: ${{ github.event_name == 'pull_request' && 'HEAD^1' || '' }}
|
||||
run: python3 tools/check_addresses.py ${BASE:+--base "$BASE"}
|
||||
# docs/layers.md#file-size: a Rust file over 3000 lines may not grow (pull requests; main has no base to compare).
|
||||
- name: Big files don't grow
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
run: python3 tools/check_file_size.py ${BASE_SHA:+--base "$BASE_SHA"}
|
||||
BASE: ${{ github.event_name == 'pull_request' && 'HEAD^1' || '' }}
|
||||
run: python3 tools/check_file_size.py ${BASE:+--base "$BASE"}
|
||||
- name: Test offline research tooling
|
||||
run: python -m unittest discover -s tests -v
|
||||
- name: Install Rust toolchain and the ALSA and udev headers the client links against
|
||||
|
||||
@@ -201,6 +201,9 @@ jobs:
|
||||
- name: Verify Windows executable architecture
|
||||
if: runner.os == 'Windows'
|
||||
run: python ../tools/check_pe_arch.py "${{ matrix.pe_arch }}" "$BIN/${{ matrix.binary }}"
|
||||
- name: Unrelated DLLs cannot intercept launcher or setup startup
|
||||
if: runner.os == 'Windows'
|
||||
run: python ../tools/test_launcher_dll_search.py "$BIN/${{ matrix.binary }}"
|
||||
- name: The version is the release's
|
||||
run: |
|
||||
out=$("$BIN/${{ matrix.binary }}" --version)
|
||||
|
||||
@@ -186,7 +186,7 @@ state stays separate from the library tests. This compiles gameplay twice for ex
|
||||
| Resource packs | L: `packs.rs` + `packs/`, `pack_screen.rs`, `atlas_sources.rs`, `sprites.rs`, `mipmap.rs`, `model_library.rs`, `font.rs`, `mobs/cem.rs` + `mobs/cem_anim.rs` (OptiFine/EMF entity models and their animations); `horizon-client-core/src/lang.rs`; crates `horizon-assets`, `horizon-optifine`; G: `packs.rs` |
|
||||
| Agent control | L: `control.rs` (socket), `bin/horizon-ctl/`; G: `control.rs`, `agent.rs`, `events.rs`, `ui_control.rs` ([docs/agent-control.md](docs/agent-control.md)) |
|
||||
| Mods | crate `horizon-mods`; G: `mods.rs`; L: `mod_content.rs`, `mod_list.rs` |
|
||||
| Horizon extras, settings | L: `extras.rs`, `graphics.rs`, `settings.rs`, `minimap.rs`; G: `extras.rs`, `tweaks.rs`, `options.rs` |
|
||||
| Horizon extras, settings | L: `extras.rs`, `graphics.rs`, `settings.rs`, `minimap.rs`; G: `extras.rs` + `extras/` (each extra's glue: `mouse_tweaks.rs`, `sorting.rs`, `pvp.rs`, `reconnect.rs`), `options.rs` |
|
||||
|
||||
## How `Game` is organised
|
||||
|
||||
|
||||
@@ -1528,7 +1528,6 @@ dependencies = [
|
||||
"horizon-client-render",
|
||||
"horizon-command",
|
||||
"horizon-core",
|
||||
"horizon-cosmetics",
|
||||
"horizon-friends",
|
||||
"horizon-hdr",
|
||||
"horizon-hooks",
|
||||
@@ -1587,6 +1586,7 @@ dependencies = [
|
||||
"horizon-core",
|
||||
"horizon-cosmetics",
|
||||
"horizon-hdr",
|
||||
"horizon-hooks",
|
||||
"horizon-items",
|
||||
"horizon-narrator",
|
||||
"horizon-optifine",
|
||||
@@ -1814,8 +1814,13 @@ dependencies = [
|
||||
name = "horizon-platform"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"horizon-core",
|
||||
"horizon-hooks",
|
||||
"horizon-prepare",
|
||||
"horizon-protocol",
|
||||
"horizon-server-files",
|
||||
"horizon-system",
|
||||
"horizon-world",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1901,11 +1906,9 @@ dependencies = [
|
||||
"horizon-anticheat",
|
||||
"horizon-bench",
|
||||
"horizon-chat-filter",
|
||||
"horizon-core",
|
||||
"horizon-mcp",
|
||||
"horizon-platform",
|
||||
"horizon-release-sign",
|
||||
"horizon-server-files",
|
||||
"horizon-world",
|
||||
"libc",
|
||||
"p12-keystore",
|
||||
"png",
|
||||
|
||||
@@ -80,8 +80,8 @@ pub fn main(args: &[String]) -> Result<(), String> {
|
||||
};
|
||||
let author = flag(rest, "--author").ok_or(USAGE)?;
|
||||
let (base, _) = registry::load(Path::new(base)).map_err(lines)?;
|
||||
let (head, _) = registry::load(Path::new(head)).map_err(lines)?;
|
||||
let review = registry::review(&base, &head, author);
|
||||
let (head, revoked) = registry::load(Path::new(head)).map_err(lines)?;
|
||||
let review = registry::review_with_revoked(&base, &head, &revoked, author);
|
||||
if rest.iter().any(|a| a == "--json") {
|
||||
let json = serde_json::json!({"errors": review.errors, "notes": review.notes});
|
||||
println!("{json}");
|
||||
|
||||
@@ -26,18 +26,23 @@ pub struct AnimationMetadata {
|
||||
pub enum ClipMode {
|
||||
/// `day_time`: frame 0 at time 0, the last at the cycle's end, then again.
|
||||
DayTime { cycle: i64 },
|
||||
/// `screen_time`: the ticks the open screen has been open, over the cycle, held on the last
|
||||
/// frame once it has run (it doesn't loop, measured on the real mod).
|
||||
ScreenTime { cycle: i64 },
|
||||
/// `weather`: frame 0 in clear weather, 1 in rain, 2 in a storm (the rain and thunder levels
|
||||
/// added up), at most the last.
|
||||
Weather,
|
||||
/// A Polytone expression: its value's fraction is how far through the animation it is.
|
||||
Expression(String),
|
||||
/// `game_time`, `screen_time`, `season`: not driven yet; the animation runs on ticks.
|
||||
/// `game_time`, `season`: not driven; the animation runs on ticks.
|
||||
Unsupported(String),
|
||||
}
|
||||
|
||||
/// The values [`ClipMode`]s read this frame.
|
||||
pub struct ModeInputs<'a> {
|
||||
pub day_time: i64,
|
||||
/// The ticks the open screen has been open (0 without one).
|
||||
pub screen_time: i64,
|
||||
/// The rain level plus the thunder level, 0 to 2.
|
||||
pub weather: f32,
|
||||
/// An expression's value this frame, by its source.
|
||||
@@ -116,7 +121,8 @@ impl AnimationMetadata {
|
||||
match mode.as_str() {
|
||||
"day_time" => ClipMode::DayTime { cycle },
|
||||
"weather" => ClipMode::Weather,
|
||||
"game_time" | "screen_time" | "season" => ClipMode::Unsupported(mode),
|
||||
"screen_time" => ClipMode::ScreenTime { cycle },
|
||||
"game_time" | "season" => ClipMode::Unsupported(mode),
|
||||
_ => ClipMode::Expression(mode),
|
||||
}
|
||||
}),
|
||||
@@ -239,6 +245,9 @@ impl AnimationClip {
|
||||
pub fn sample_mode(&self, inputs: &ModeInputs) -> Option<AnimationSample> {
|
||||
let fraction = match self.mode.as_ref()? {
|
||||
ClipMode::DayTime { cycle } => day_fraction(inputs.day_time, *cycle),
|
||||
ClipMode::ScreenTime { cycle } => {
|
||||
(inputs.screen_time.max(0) as f64 / *cycle as f64).min(1.0 - f64::EPSILON)
|
||||
}
|
||||
ClipMode::Weather => {
|
||||
let last = self.sequence.len() - 1;
|
||||
let index = (inputs.weather.max(0.0) as usize).min(last);
|
||||
@@ -288,6 +297,7 @@ mod mode_tests {
|
||||
let expression = move |_: &str| Some(value);
|
||||
clip.sample_mode(&ModeInputs {
|
||||
day_time,
|
||||
screen_time: day_time,
|
||||
weather,
|
||||
expression: &expression,
|
||||
})
|
||||
@@ -302,6 +312,13 @@ mod mode_tests {
|
||||
.map(|t| frame(&day, t, 0.0, 0.0))
|
||||
.into();
|
||||
assert_eq!(frames, [0, 1, 2, 3, 1]);
|
||||
// 26.3-6.8.6, four frames over 200 ticks: 40 ticks open show the first, and from ten
|
||||
// seconds on the last, even after 27 (it doesn't loop).
|
||||
let screen = clip(r#"{"frametime": 1, "mode": "screen_time", "time_cycle_duration": 200}"#);
|
||||
let frames: Vec<u32> = [0, 40, 200, 360, 540]
|
||||
.map(|t| frame(&screen, t, 0.0, 0.0))
|
||||
.into();
|
||||
assert_eq!(frames, [0, 0, 3, 3, 3]);
|
||||
let value = clip(r#"{"frametime": 1, "mode": "0.6"}"#);
|
||||
assert_eq!(frame(&value, 0, 0.0, 0.6), 2);
|
||||
assert_eq!(frame(&value, 0, 0.0, 2.0), 0);
|
||||
@@ -321,6 +338,7 @@ mod mode_tests {
|
||||
clip(r#"{"frametime": 1}"#)
|
||||
.sample_mode(&ModeInputs {
|
||||
day_time: 0,
|
||||
screen_time: 0,
|
||||
weather: 0.0,
|
||||
expression: &|_| None
|
||||
})
|
||||
@@ -330,6 +348,7 @@ mod mode_tests {
|
||||
clip(r#"{"frametime": 1, "mode": "season"}"#)
|
||||
.sample_mode(&ModeInputs {
|
||||
day_time: 0,
|
||||
screen_time: 0,
|
||||
weather: 0.0,
|
||||
expression: &|_| None
|
||||
})
|
||||
|
||||
@@ -18,8 +18,6 @@ horizon-client-core = { path = "../horizon-client-core" }
|
||||
horizon-client-input = { path = "../horizon-client-input" }
|
||||
horizon-client-render = { path = "../horizon-client-render" }
|
||||
horizon-command = { path = "../horizon-command" }
|
||||
# Emotes pose the player model (`Mob::emote`, `mobs::anim::setup`).
|
||||
horizon-cosmetics = { path = "../horizon-cosmetics" }
|
||||
horizon-items = { path = "../horizon-items" }
|
||||
horizon-core = { path = "../horizon-core" }
|
||||
# Extension points for the crates above the engine (docs/layers.md, "How a Horizon crate plugs in").
|
||||
|
||||
@@ -7,6 +7,8 @@ rust-version.workspace = true
|
||||
description = "The client's world data, rendering and screens: chunks, meshing, light, streaming, the renderer, the HUD, menus and settings; no gameplay"
|
||||
|
||||
[dependencies]
|
||||
# The settings stores of the crates above the engine (docs/layers.md, "Platform registries").
|
||||
horizon-hooks = { path = "../horizon-hooks" }
|
||||
horizon-cosmetics = { path = "../horizon-cosmetics" }
|
||||
# The GUI atlas's pixels, kept compressed once uploaded (hud.rs `pack_pixels`).
|
||||
lz4_flex = { version = "0.14", default-features = false, features = ["std", "safe-encode", "safe-decode", "checked-decode"] }
|
||||
|
||||
@@ -362,7 +362,7 @@ fn fixture_frame(hud: &HudBatch) -> Frame<'_> {
|
||||
outline: Vec::new(),
|
||||
outline_after_terrain: false,
|
||||
outline_high_contrast: false,
|
||||
pvp: Default::default(),
|
||||
look: Default::default(),
|
||||
debug_lines: &[],
|
||||
debug_lines_on_top: &[],
|
||||
debug_crosshair: &[],
|
||||
|
||||
@@ -430,7 +430,7 @@ fn fixture_frame(hud: &HudBatch) -> Frame<'_> {
|
||||
outline: Vec::new(),
|
||||
outline_after_terrain: false,
|
||||
outline_high_contrast: false,
|
||||
pvp: Default::default(),
|
||||
look: Default::default(),
|
||||
debug_lines: &[],
|
||||
debug_lines_on_top: &[],
|
||||
debug_crosshair: &[],
|
||||
|
||||
@@ -16,6 +16,45 @@ use crate::{
|
||||
#[path = "chat_tests.rs"]
|
||||
mod tests;
|
||||
|
||||
/// `FilterMask.applyWithFormatting` over a player message's signed content, as
|
||||
/// the packet's mask `(type, bit set)`: as it is when passed through, none when
|
||||
/// fully filtered, and when partly filtered each masked UTF-16 unit becomes a
|
||||
/// `#` in `FILTERED_STYLE` (dark grey, hover "chat.filtered").
|
||||
pub fn filtered_message(
|
||||
content: &str,
|
||||
(kind, bits): &(i32, Vec<i64>),
|
||||
) -> Option<serde_json::Value> {
|
||||
match kind {
|
||||
1 => return None,
|
||||
2 => {}
|
||||
_ => return Some(serde_json::Value::from(content)),
|
||||
}
|
||||
let masked = |i: usize| {
|
||||
bits.get(i / 64)
|
||||
.is_some_and(|w| (*w as u64 >> (i % 64)) & 1 != 0)
|
||||
};
|
||||
let units: Vec<u16> = content.encode_utf16().collect();
|
||||
let mut parts = Vec::new();
|
||||
let mut start = 0;
|
||||
while start < units.len() {
|
||||
let filtered = masked(start);
|
||||
let end = (start..units.len())
|
||||
.find(|&i| masked(i) != filtered)
|
||||
.unwrap_or(units.len());
|
||||
parts.push(if filtered {
|
||||
serde_json::json!({
|
||||
"text": "#".repeat(end - start),
|
||||
"color": "dark_gray",
|
||||
"hover_event": {"action": "show_text", "value": {"translate": "chat.filtered"}},
|
||||
})
|
||||
} else {
|
||||
serde_json::Value::from(String::from_utf16_lossy(&units[start..end]))
|
||||
});
|
||||
start = end;
|
||||
}
|
||||
Some(serde_json::json!({"text": "", "extra": parts}))
|
||||
}
|
||||
|
||||
/// `CommandHistory.PERSISTED_COMMANDS_FILE_NAME` and its size cap.
|
||||
const COMMAND_HISTORY_FILE: &str = "command_history.txt";
|
||||
const MAX_PERSISTED_COMMAND_HISTORY: usize = 50;
|
||||
|
||||
@@ -1026,3 +1026,43 @@ fn a_compact_repeat_keeps_the_scrolled_view_still() {
|
||||
says(&mut chat, "new");
|
||||
assert_eq!(chat.scroll, 6);
|
||||
}
|
||||
|
||||
/// `FilterMask.applyWithFormatting`: a pass-through mask keeps the message, a
|
||||
/// fully filtered one hides it, and a partial one turns each masked UTF-16 unit
|
||||
/// into a dark grey `#` whose hover reads `chat.filtered`.
|
||||
#[test]
|
||||
fn a_server_filter_mask_hides_or_masks_the_message() {
|
||||
let text = |v: &serde_json::Value| crate::component::to_text(v, &mut |s| Text::literal(s));
|
||||
let shown = |content: &str, mask: (i32, Vec<i64>)| {
|
||||
filtered_message(content, &mask).map(|v| text(&v).plain())
|
||||
};
|
||||
assert_eq!(shown("hello", (0, vec![])), Some("hello".to_owned()));
|
||||
assert_eq!(shown("hello", (1, vec![])), None);
|
||||
assert_eq!(shown("hello", (2, vec![0b0110])), Some("h##lo".to_owned()));
|
||||
assert_eq!(
|
||||
shown("hello", (2, vec![0b1_0001])),
|
||||
Some("#ell#".to_owned())
|
||||
);
|
||||
// An emoji is two UTF-16 units, so two bits and two `#`.
|
||||
assert_eq!(
|
||||
shown("a\u{1F600}b", (2, vec![0b0110])),
|
||||
Some("a##b".to_owned())
|
||||
);
|
||||
// Bit 65 is in the second word.
|
||||
let long = "x".repeat(70);
|
||||
let mut expected = long.clone();
|
||||
expected.replace_range(65..66, "#");
|
||||
assert_eq!(shown(&long, (2, vec![0, 0b10])), Some(expected));
|
||||
let masked = text(&filtered_message("hello", &(2, vec![0b0110])).unwrap());
|
||||
let hash = masked.spans.iter().find(|s| s.text == "##").unwrap();
|
||||
assert_eq!(hash.style.color, Some(text::DARK_GRAY));
|
||||
let hover = hash.style.hover.as_ref().unwrap();
|
||||
assert_eq!(hover.spans[0].text, "chat.filtered");
|
||||
assert!(
|
||||
masked
|
||||
.spans
|
||||
.iter()
|
||||
.filter(|s| s.text != "##")
|
||||
.all(|s| s.style.color.is_none())
|
||||
);
|
||||
}
|
||||
@@ -43,6 +43,11 @@ pub fn enter_native_mod(call: NativeModCall) -> NativeModGuard {
|
||||
}
|
||||
}
|
||||
|
||||
/// The native mod call this thread is currently inside, if any.
|
||||
pub fn current_native_mod() -> Option<NativeModCall> {
|
||||
IN_NATIVE_MOD.with(Cell::get)
|
||||
}
|
||||
|
||||
/// Puts back the call that `enter_native_mod` found.
|
||||
#[must_use]
|
||||
pub struct NativeModGuard {
|
||||
|
||||
@@ -305,6 +305,9 @@ pub(crate) struct Colormap {
|
||||
/// (`temperature`, `downfall`, `biome_id`) blend: Polytone 6.8.6's water by `biome_id`
|
||||
/// fades over a biome edge.
|
||||
pub(crate) biome_blend: bool,
|
||||
/// Its axes read nothing that changes up a column of one biome (no `o.y`): a section of
|
||||
/// one biome can sample it once per column.
|
||||
pub(crate) column: bool,
|
||||
width: u32,
|
||||
height: u32,
|
||||
rgba: Vec<u8>,
|
||||
@@ -323,6 +326,18 @@ enum Axis {
|
||||
}
|
||||
|
||||
impl Axis {
|
||||
/// Whether the axis reads only what stays the same up a column of one biome.
|
||||
fn column(&self) -> bool {
|
||||
use horizon_polytone::expr::Root;
|
||||
let flat = |root: Root, name: &str| match root {
|
||||
Root::Object => matches!(name, "x" | "z" | "biome" | "temperature" | "downfall"),
|
||||
Root::Random => name == "noise",
|
||||
_ => false,
|
||||
};
|
||||
match self {
|
||||
Self::Expr(program) | Self::BiomeId(_, program) => program.reads_only(&flat),
|
||||
}
|
||||
}
|
||||
fn value(&self, host: &mut dyn horizon_polytone::expr::Host) -> Option<f64> {
|
||||
match self {
|
||||
Self::Expr(program) => Some(program.eval(host).ok()?.num()),
|
||||
@@ -373,6 +388,23 @@ fn biome_id_mapper(pack_root: &Path, json: &Json) -> HashMap<String, f64> {
|
||||
}
|
||||
|
||||
impl Colormap {
|
||||
/// One colour wherever it samples (a `biome_colors` flat colour, RGB).
|
||||
pub(crate) fn flat(rgb: u32) -> Self {
|
||||
let zero = || Axis::Expr(horizon_polytone::expr::Program::compile("0").expect("a number"));
|
||||
let [_, r, g, b] = rgb.to_be_bytes();
|
||||
Self {
|
||||
x: zero(),
|
||||
y: zero(),
|
||||
triangular: false,
|
||||
rounds: true,
|
||||
biome_blend: false,
|
||||
column: true,
|
||||
width: 1,
|
||||
height: 1,
|
||||
rgba: vec![r, g, b, 255],
|
||||
}
|
||||
}
|
||||
|
||||
/// `assets/<namespace>/polytone/colormaps/<path>.png` and its optional `.json` (without
|
||||
/// one, the axes are the biome's temperature and downfall).
|
||||
pub(crate) fn load(pack_root: &Path, id: &str) -> Option<Self> {
|
||||
@@ -424,9 +456,11 @@ impl Colormap {
|
||||
axis("x_axis", "o.temperature")?,
|
||||
axis("y_axis", "o.downfall")?,
|
||||
);
|
||||
let column = [&x, &y].iter().all(|axis| axis.column());
|
||||
Some(Self {
|
||||
x,
|
||||
y,
|
||||
column,
|
||||
biome_blend: json["biome_blend"].as_bool().unwrap_or(by_biome),
|
||||
triangular: json["triangular"].as_bool() == Some(true),
|
||||
rounds: json["rounds"].as_bool() != Some(false),
|
||||
|
||||
@@ -482,13 +482,16 @@ impl Extras {
|
||||
true
|
||||
}
|
||||
/// Written only once something differs from the defaults, so a vanilla
|
||||
/// setup gains no file.
|
||||
/// setup gains no file. The settings stores of this file follow these lines
|
||||
/// (`horizon_hooks::settings`).
|
||||
pub fn save(&self, dir: &Path) {
|
||||
let path = dir.join(FILE);
|
||||
if *self == Self::default() && !path.exists() {
|
||||
let mut text = self.serialize();
|
||||
let stores_default = horizon_hooks::settings::engine::append(FILE, &mut text);
|
||||
if *self == Self::default() && stores_default && !path.exists() {
|
||||
return;
|
||||
}
|
||||
let _ = fs::write(path, self.serialize());
|
||||
let _ = fs::write(path, text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ fn packed_wanted() -> bool {
|
||||
std::env::var("HORIZON_PACKED_QUADS").as_deref() != Ok("0")
|
||||
}
|
||||
|
||||
mod animate;
|
||||
pub(crate) mod animate;
|
||||
mod arena;
|
||||
pub mod capture;
|
||||
pub mod compositor;
|
||||
@@ -1001,8 +1001,8 @@ pub struct Frame<'a> {
|
||||
pub outline_after_terrain: bool,
|
||||
/// `BlockOutlineRenderState.highContrast`: a thick black outline under a bright one.
|
||||
pub outline_high_contrast: bool,
|
||||
/// The PvP & HUD page's outline and hit colour (`pvp::Frame`; default: vanilla's).
|
||||
pub pvp: crate::pvp::Frame,
|
||||
/// The outline, hurt overlay and glint colours a crate above set (`horizon_hooks::look`).
|
||||
pub look: horizon_hooks::look::Frame,
|
||||
/// `lines` with a colour and pixel width (`gizmos::camera_relative`):
|
||||
/// the fishing line and debug gizmos, depth tested, then gizmos drawn
|
||||
/// over everything.
|
||||
@@ -1530,6 +1530,8 @@ pub struct Renderer {
|
||||
output_caps: output::OutputCapabilities,
|
||||
/// An output that failed to apply, not tried again until something it needs changes.
|
||||
output_rejected: Option<output_apply::Rejected>,
|
||||
/// Since when Auto keeps HDR on through the display's loss of its report.
|
||||
auto_off_since: Option<std::time::Instant>,
|
||||
/// The output applied (`update_output`), with the frame every pipeline that draws it
|
||||
/// targets: the swapchain's 8-bit format, or `Rgba16Unorm` when the renderer was made with
|
||||
/// HDR output on and Smooth Gradients and the device draws and blends into it, or
|
||||
@@ -4247,16 +4249,13 @@ impl Renderer {
|
||||
CRUMBLING_BLEND,
|
||||
false,
|
||||
);
|
||||
// RenderPipelines.ENTITY_SHADOW: translucent, back-face culled, depth
|
||||
// test without writes. The quads lie exactly on the block tops like
|
||||
// vanilla's, facing +Y so looking up from below culls them, but
|
||||
// terrain and shadows are separate draw paths, so their fp32 depth
|
||||
// interpolations disagree by a few dozen ulps of the fragment depth
|
||||
// and the shadow's rim z-fights with the block top (speckle that
|
||||
// re-rolls as the camera drifts a subpixel). A constant bias of 128
|
||||
// ulps covers that spread at any resolution while staying far below
|
||||
// the 0.001 a model's feet sit higher, so shadows never bleed onto
|
||||
// the feet.
|
||||
// RenderPipelines.ENTITY_SHADOW: translucent, back-face culled, depth test without writes.
|
||||
// The quads lie exactly on the block tops like vanilla's, facing +Y so looking up from
|
||||
// below culls them, but terrain and shadows are separate draw paths, so their fp32 depth
|
||||
// interpolations disagree by a few dozen ulps of the fragment depth and the shadow's rim
|
||||
// z-fights with the block top (speckle that re-rolls as the camera drifts a subpixel). A
|
||||
// constant bias of 128 ulps covers that spread at any resolution while staying far below
|
||||
// the 0.001 a model's feet sit higher, so shadows never bleed onto the feet.
|
||||
let shadow_blob_pipeline = entity_pipeline_with(
|
||||
"Entity shadows",
|
||||
Some(wgpu::Face::Back),
|
||||
@@ -5355,6 +5354,7 @@ impl Renderer {
|
||||
emission_stats,
|
||||
output_caps,
|
||||
output_rejected: None,
|
||||
auto_off_since: None,
|
||||
// Nothing is presented as HDR yet: `update_output` applies the settings.
|
||||
output: output::resolve_output(settings, output_caps, display, frame, false),
|
||||
frame_kept_logged: false,
|
||||
@@ -7094,11 +7094,6 @@ impl Renderer {
|
||||
horizon_hdr::set_metadata(&self.device, surface, hdr.declared_peak(), hdr.black);
|
||||
}
|
||||
}
|
||||
/// The swapchain's configuration: `config` (what every pipeline draws in), or
|
||||
/// HDR10 or scRGB while HDR output is on.
|
||||
fn surface_config(&self) -> wgpu::SurfaceConfiguration {
|
||||
output_apply::surface_config(&self.config, self.hdr.as_ref().map(|hdr| hdr.output))
|
||||
}
|
||||
/// This renderer's output as applied, with what its destination offers and reports.
|
||||
pub fn output(&self) -> &output::EffectiveOutput {
|
||||
&self.output
|
||||
@@ -7154,7 +7149,7 @@ impl Renderer {
|
||||
settings,
|
||||
request,
|
||||
self.caps_for(settings),
|
||||
self.reading,
|
||||
output_apply::graced(self.auto_off_since, self.reading, &self.output),
|
||||
self.config.format,
|
||||
)
|
||||
}
|
||||
@@ -8354,8 +8349,12 @@ impl Renderer {
|
||||
t.begin(&self.device, &self.queue);
|
||||
}
|
||||
if self.animated_textures {
|
||||
self.hud
|
||||
.animate_sprites(&mut self.uploads, &mut encoder, frame.ticks);
|
||||
self.hud.animate(
|
||||
&mut self.uploads,
|
||||
&mut encoder,
|
||||
frame.ticks,
|
||||
&self.animations,
|
||||
);
|
||||
}
|
||||
self.update_lightmap(
|
||||
&mut encoder,
|
||||
@@ -8507,9 +8506,9 @@ impl Renderer {
|
||||
colored_count: [
|
||||
frame.colored_lights.len().min(crate::dynamic_light::MAX) as u32,
|
||||
// PvP & HUD's hit colour: entity.wgsl's hurt texel, 0 for vanilla's.
|
||||
frame.pvp.hurt_texel,
|
||||
frame.look.hurt_texel,
|
||||
// PvP & HUD's glint colour: entity.wgsl's `tinted_glint`, 0 for vanilla's.
|
||||
frame.pvp.glint,
|
||||
frame.look.glint,
|
||||
0,
|
||||
],
|
||||
emissive_layers: {
|
||||
@@ -9293,13 +9292,11 @@ impl Renderer {
|
||||
}
|
||||
// Near water and distant water share one back-to-front draw order.
|
||||
if self.translucent_draws.len() > section_translucent {
|
||||
// Distant water goes after the near chunks', and replaced tiles'
|
||||
// after all: each is a hair behind the one before, so depth leaves
|
||||
// it only where that one has none. Back to front together, a far
|
||||
// tile's water under a near chunk's (one fading in, or brought
|
||||
// into view by a longer render distance) blended twice and looked
|
||||
// opaque. The cost: far water just behind near water shows no
|
||||
// surface of its own there.
|
||||
// Distant water goes after the near chunks', and replaced tiles' after all: each is a
|
||||
// hair behind the one before, so depth leaves it only where that one has none. Back to
|
||||
// front together, a far tile's water under a near chunk's (one fading in, or brought
|
||||
// into view by a longer render distance) blended twice and looked opaque. The cost: far
|
||||
// water just behind near water shows no surface of its own there.
|
||||
let tier = |instance: usize| match instance.checked_sub(visible.len()) {
|
||||
None => 0,
|
||||
Some(tile) if visible_lods[tile].old => 2,
|
||||
@@ -9498,7 +9495,7 @@ impl Renderer {
|
||||
}
|
||||
};
|
||||
// A custom outline (PvP & HUD) takes the bright stroke's colour, scales both widths.
|
||||
let (custom, scale) = frame.pvp.outline.map_or((None, 1.0), |(c, s)| (Some(c), s));
|
||||
let (custom, scale) = frame.look.outline.map_or((None, 1.0), |o| (Some(o.0), o.1));
|
||||
if frame.outline_high_contrast {
|
||||
stroke(0xff00_0000, 7.0 * scale, lines);
|
||||
stroke(custom.unwrap_or(0xff57_ffe1), width * scale, lines);
|
||||
|
||||
@@ -64,7 +64,7 @@ enum Writer {
|
||||
},
|
||||
}
|
||||
|
||||
pub(super) struct SpriteAnimator {
|
||||
pub(crate) struct SpriteAnimator {
|
||||
sprites: Vec<Sprite>,
|
||||
groups: Vec<Group>,
|
||||
writer: Writer,
|
||||
@@ -86,6 +86,9 @@ struct AnimationModes {
|
||||
day_time: i64,
|
||||
weather: f32,
|
||||
values: std::collections::HashMap<String, f64>,
|
||||
/// The open screen (an identity the game picks) and the ticks it has been open.
|
||||
screen: Option<u64>,
|
||||
screen_time: i64,
|
||||
}
|
||||
|
||||
impl AnimationModes {
|
||||
@@ -116,8 +119,15 @@ impl super::Renderer {
|
||||
day_time: i64,
|
||||
[rain, thunder]: [f32; 2],
|
||||
frame: Option<&crate::environment::Frame>,
|
||||
screen: Option<u64>,
|
||||
) {
|
||||
let modes = &mut self.animations.modes;
|
||||
// `screen_time`: a tick more while the same screen stays open, from 0 on a new one.
|
||||
modes.screen_time = match (screen, modes.screen) {
|
||||
(Some(open), Some(was)) if open == was => modes.screen_time + 1,
|
||||
_ => 0,
|
||||
};
|
||||
modes.screen = screen;
|
||||
modes.day_time = day_time;
|
||||
modes.weather = rain + thunder;
|
||||
modes.values.clear();
|
||||
@@ -133,6 +143,16 @@ impl super::Renderer {
|
||||
}
|
||||
|
||||
impl SpriteAnimator {
|
||||
/// What the modes read this frame, for the GUI atlas's sprites (their expressions aren't
|
||||
/// compiled: those run on ticks).
|
||||
pub(crate) fn mode_inputs(&self) -> horizon_assets::animation::ModeInputs<'static> {
|
||||
horizon_assets::animation::ModeInputs {
|
||||
day_time: self.modes.day_time,
|
||||
screen_time: self.modes.screen_time,
|
||||
weather: self.modes.weather,
|
||||
expression: &|_| None,
|
||||
}
|
||||
}
|
||||
/// `textures` are the sprite arrays, `split` layers each, `size` pixels
|
||||
/// wide; `animations` hold their frames at that size. `compute`: whether
|
||||
/// the device says it runs compute shaders writing storage textures.
|
||||
@@ -361,6 +381,7 @@ impl SpriteAnimator {
|
||||
let expression = |source: &str| values.get(source).copied();
|
||||
let inputs = horizon_assets::animation::ModeInputs {
|
||||
day_time: self.modes.day_time,
|
||||
screen_time: self.modes.screen_time,
|
||||
weather: self.modes.weather,
|
||||
expression: &expression,
|
||||
};
|
||||
|
||||
@@ -524,7 +524,7 @@ impl Scene {
|
||||
outline: Vec::new(),
|
||||
outline_after_terrain: false,
|
||||
outline_high_contrast: false,
|
||||
pvp: Default::default(),
|
||||
look: Default::default(),
|
||||
debug_lines: &[],
|
||||
debug_lines_on_top: &[],
|
||||
debug_crosshair: &[],
|
||||
|
||||
@@ -185,7 +185,7 @@ pub struct Hdr {
|
||||
/// The display's black level, in nits: shadows are lifted onto it (`hdr.wgsl`).
|
||||
pub black: f32,
|
||||
pub tiers: [Tier; 4],
|
||||
/// The HUD and menus' brightness, as a share of paper white (0.25..=1).
|
||||
/// The HUD and menus' brightness, as a share of paper white: above 1 brighter than it.
|
||||
pub ui: f32,
|
||||
/// Which pixels of a light source shine (`Masks`).
|
||||
pub masks: Masks,
|
||||
@@ -956,7 +956,7 @@ impl Hdr {
|
||||
f32::from(u8::from(pq)),
|
||||
]);
|
||||
params[5] = self.black.clamp(0.0, paper);
|
||||
params[6] = self.ui.clamp(0.25, 1.0);
|
||||
params[6] = self.ui;
|
||||
params[7] = if self.lighting {
|
||||
scene_gain(self.peak, self.paper_white)
|
||||
} else {
|
||||
@@ -1906,9 +1906,11 @@ struct ReferenceParams { peak: f32, scene: f32, world: f32, debug: f32, share: v
|
||||
// Covered: the HUD as drawn, at UI Brightness.
|
||||
(2.0, 0.3, 1.0, 1.0, 0.3),
|
||||
(2.0, 0.3, 1.0, 0.5, 0.3 * 0.5f32.powf(1.0 / 2.2)),
|
||||
// UI Brightness above paper white: brighter than drawn.
|
||||
(2.0, 0.3, 1.0, 2.0, 0.3 * 2f32.powf(1.0 / 2.2)),
|
||||
// Added over the world (the text highlight), which it doesn't hide.
|
||||
(0.6, 0.8, 0.0, 1.0, 0.8),
|
||||
// At or below white, at 100%: the HUD's picture as drawn.
|
||||
// At or below white, at paper white: the HUD's picture as drawn.
|
||||
(0.7, 0.45, 0.5, 1.0, 0.45),
|
||||
] {
|
||||
hdr.ui = ui;
|
||||
@@ -1928,6 +1930,50 @@ struct ReferenceParams { peak: f32, scene: f32, world: f32, debug: f32, share: v
|
||||
}
|
||||
}
|
||||
|
||||
/// On the frame without the HUD's layer, the HUD at UI Brightness reaches its nits, and
|
||||
/// above the peak stops there, as on the layered frame.
|
||||
#[test]
|
||||
fn the_hud_at_ui_brightness_stops_at_the_peak() {
|
||||
let Some((device, queue)) = gpu() else {
|
||||
return;
|
||||
};
|
||||
let mut hdr = Hdr::with_debug(&device, &queue, F::Rgba8Unorm, Output::ScRgb, false, None);
|
||||
(hdr.paper_white, hdr.peak) = (200.0, 300.0);
|
||||
let target = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: wgpu::Extent3d {
|
||||
width: 1,
|
||||
height: 1,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: Output::ScRgb.format(),
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC,
|
||||
view_formats: &[],
|
||||
});
|
||||
// UI Brightness (a share of paper white) and the white HUD's nits.
|
||||
for (ui, want) in [(0.5, 100.0), (1.25, 250.0), (2.0, 300.0)] {
|
||||
hdr.ui = ui;
|
||||
let frame = hdr.frame(&device, [1, 1]);
|
||||
let mut encoder = device.create_command_encoder(&Default::default());
|
||||
fill(&mut encoder, &frame, [0.2, 0.2, 0.2, 1.0]);
|
||||
hdr.keep_world(&mut encoder, None);
|
||||
// Opaque white HUD over the world: alpha 1 is full coverage.
|
||||
fill(&mut encoder, &frame, [1.0; 4]);
|
||||
hdr.begin(&queue, true);
|
||||
hdr.present(&queue, &mut encoder, &target, true, None);
|
||||
let got = texel(&device, &queue, encoder, &target);
|
||||
for c in &got[..3] {
|
||||
assert!(
|
||||
(c * 80.0 - want).abs() < 0.5,
|
||||
"UI {ui}: {got:?}, not {want} nits"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_menu_blur_keeps_the_light_it_blurs() {
|
||||
let Some((device, queue)) = gpu() else {
|
||||
|
||||
@@ -142,7 +142,7 @@ pub struct EffectiveOutput {
|
||||
/// Paper white, peak and black level in nits, as HDR output's last pass and its
|
||||
/// metadata take them, while it is on.
|
||||
pub(crate) nits: [f32; 3],
|
||||
/// The HUD and menus' brightness, as a share of paper white.
|
||||
/// The HUD and menus' brightness, as a share of paper white: their nits over its.
|
||||
pub(crate) ui_brightness: f32,
|
||||
}
|
||||
impl Default for EffectiveOutput {
|
||||
@@ -271,7 +271,8 @@ pub(crate) fn resolve_output(
|
||||
settings.peak_nits(reading.luminance) as f32,
|
||||
settings.black_level_nits(),
|
||||
],
|
||||
ui_brightness: settings.hdr_ui_brightness as f32 / 100.0,
|
||||
ui_brightness: settings.ui_nits(reading.luminance) as f32
|
||||
/ settings.paper_white_nits(reading.luminance) as f32,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,6 +567,39 @@ pub(crate) mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// UI Brightness reaches HDR output as its nits over paper white's: 1 on Auto, whatever
|
||||
/// paper white is; a value set by hand holds its nits, Paper White on Auto or set by hand.
|
||||
#[test]
|
||||
fn ui_brightness_is_its_nits_over_paper_whites() {
|
||||
let (caps, reading) = window(Some(Output::Pq), Some(true));
|
||||
let share = |paper_white, ui_nits, reading| {
|
||||
let settings = Graphics {
|
||||
hdr: HdrMode::On,
|
||||
hdr_paper_white: paper_white,
|
||||
hdr_ui_nits: ui_nits,
|
||||
..Graphics::default()
|
||||
};
|
||||
let frame = resolve_frame(
|
||||
&settings,
|
||||
FrameRequest::default(),
|
||||
caps,
|
||||
reading,
|
||||
Bgra8Unorm,
|
||||
);
|
||||
resolve_output(&settings, caps, reading, frame, true).ui_brightness
|
||||
};
|
||||
// Auto: the report's 400 nits, 203 without one, or the player's 250.
|
||||
let unreported = DisplayReading::default();
|
||||
for (paper_white, reading) in [(0, reading), (0, unreported), (250, reading)] {
|
||||
assert_eq!(share(paper_white, 0, reading), 1.0);
|
||||
}
|
||||
assert_eq!(share(0, 100, reading), 0.25);
|
||||
assert_eq!(share(0, 480, reading), 1.2);
|
||||
assert_eq!(share(0, 406, unreported), 2.0);
|
||||
assert_eq!(share(250, 100, reading), 0.4);
|
||||
assert_eq!(share(250, 480, reading), 1.92);
|
||||
}
|
||||
|
||||
/// Two renderers' states, a window's and an offscreen one's, made and changed in turn:
|
||||
/// neither's offer or report shows in the other's snapshot, and the offscreen one
|
||||
/// stopping its watch (HDR Off) leaves the window's report alone.
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
//! changes only values (the luminance, the UI brightness, what the display reports) updates
|
||||
//! them in place. Another encoding or frame is built and the swapchain configured for it before
|
||||
//! the snapshot says so. One that fails is never published as active, and is not tried again
|
||||
//! until the request, the capabilities or the surface change.
|
||||
//! until the request, the capabilities or the surface change. Auto keeps HDR on through a
|
||||
//! moment's loss of the display's report ([`auto_grace`]).
|
||||
use super::{DisplayReading, DisplayWatch, Renderer, hdr, output};
|
||||
use crate::graphics::HdrMode;
|
||||
use output::{EffectiveOutput, OutputCapabilities};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
/// What an output's resources are made for: the encoding presented and the frame.
|
||||
type Key = (Option<hdr::Output>, output::FrameConfiguration);
|
||||
@@ -101,6 +104,98 @@ pub(super) fn surface_config(
|
||||
config
|
||||
}
|
||||
|
||||
/// How long Auto keeps HDR on once the display stops reporting it. A fixed window that
|
||||
/// coalesces the report's churn as a display wakes or the window moves to another one; not a
|
||||
/// measured sleep/wake time.
|
||||
const AUTO_OFF_DELAY: Duration = Duration::from_millis(500);
|
||||
|
||||
/// The display's report `update_output` resolves Auto with at `now`. While Auto presents HDR
|
||||
/// and the surface still offers that encoding, a report that turns false or unknown starts
|
||||
/// the timer `since`, once, and HDR stays on at the values last applied until it has held
|
||||
/// for [`AUTO_OFF_DELAY`]; a positive report before then clears it. Off and On, a changed
|
||||
/// offer, and entering HDR take `raw` at once.
|
||||
fn auto_grace(
|
||||
now: Instant,
|
||||
mode: HdrMode,
|
||||
offered: Option<hdr::Output>,
|
||||
raw: DisplayReading,
|
||||
applied: &EffectiveOutput,
|
||||
since: &mut Option<Instant>,
|
||||
) -> DisplayReading {
|
||||
let lost = mode == HdrMode::Auto
|
||||
&& applied.encoding.is_some()
|
||||
&& offered == applied.encoding
|
||||
&& raw.hdr != Some(true);
|
||||
if !lost {
|
||||
if since.take().is_some() && raw.hdr == Some(true) {
|
||||
log::info!("Horizon renderer: the display reports HDR again; HDR stays on");
|
||||
}
|
||||
} else if since.is_none() {
|
||||
log::info!(
|
||||
"Horizon renderer: the display stopped reporting HDR; Auto keeps it on for {} ms",
|
||||
AUTO_OFF_DELAY.as_millis()
|
||||
);
|
||||
*since = Some(now);
|
||||
} else if grace_over(*since, now) {
|
||||
*since = None;
|
||||
}
|
||||
graced(*since, raw, applied)
|
||||
}
|
||||
|
||||
fn grace_over(since: Option<Instant>, now: Instant) -> bool {
|
||||
since.is_some_and(|since| now.saturating_duration_since(since) >= AUTO_OFF_DELAY)
|
||||
}
|
||||
|
||||
/// What the display reports as the output takes it: during Auto's grace (`since`), HDR at the
|
||||
/// luminance `applied` was resolved with; `raw` otherwise.
|
||||
pub(super) fn graced(
|
||||
since: Option<Instant>,
|
||||
raw: DisplayReading,
|
||||
applied: &EffectiveOutput,
|
||||
) -> DisplayReading {
|
||||
match since {
|
||||
Some(_) => DisplayReading {
|
||||
luminance: applied.reported,
|
||||
hdr: Some(true),
|
||||
},
|
||||
None => raw,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the output resolves again at `now`: a due poll (`read`, with the surface's
|
||||
/// `offer`; on Wayland, an event) changed `reading` or `caps`, or Auto's grace `since` is
|
||||
/// over. Its end reads the display once more first, however long until the next poll, unless
|
||||
/// a read since the deadline did (the last read is a `DISPLAY_POLL` before the next).
|
||||
fn poll_display(
|
||||
watch: Option<&mut DisplayWatch>,
|
||||
reading: &mut DisplayReading,
|
||||
caps: &mut OutputCapabilities,
|
||||
since: Option<Instant>,
|
||||
now: Instant,
|
||||
read: impl FnOnce() -> DisplayReading,
|
||||
offer: impl FnOnce() -> Option<Option<hdr::Output>>,
|
||||
) -> bool {
|
||||
let over = grace_over(since, now);
|
||||
let Some(watch) = watch else {
|
||||
return over;
|
||||
};
|
||||
if let (Some(since), Some(next)) = (since.filter(|_| over), &mut watch.polled)
|
||||
&& *next < since + AUTO_OFF_DELAY + super::DISPLAY_POLL
|
||||
{
|
||||
*next = now;
|
||||
}
|
||||
let Some(read) = watch.poll(*reading, now, read) else {
|
||||
return over;
|
||||
};
|
||||
observe(reading, caps, read, offer()) || over
|
||||
}
|
||||
|
||||
/// What `surface` offers now (`None` offscreen): Vulkan's offered formats can change with
|
||||
/// desktop HDR or the window's output, and a display can offer the other encoding.
|
||||
fn offer(surface: Option<&wgpu::Surface>, adapter: &wgpu::Adapter) -> Option<Option<hdr::Output>> {
|
||||
Some(hdr::output(&surface?.get_capabilities(adapter)))
|
||||
}
|
||||
|
||||
/// Takes what a due poll read into `reading` and `caps`: the display's report `now`, and what
|
||||
/// the surface offers (`offer`, `None` without a surface). Whether either changed, the offer
|
||||
/// alone included.
|
||||
@@ -219,12 +314,26 @@ impl Renderer {
|
||||
settings: &crate::graphics::Graphics,
|
||||
marker: &std::path::Path,
|
||||
) {
|
||||
let now = Instant::now();
|
||||
self.watch_hdr(settings.hdr);
|
||||
// Auto's grace ends on a fresh read, also where a settings change comes before the
|
||||
// frame's `display_changed`.
|
||||
if grace_over(self.auto_off_since, now) {
|
||||
self.read_display(now);
|
||||
}
|
||||
self.hold_hdr_back(settings);
|
||||
let reading = auto_grace(
|
||||
now,
|
||||
settings.hdr,
|
||||
self.output_caps.hdr,
|
||||
self.reading,
|
||||
&self.output,
|
||||
&mut self.auto_off_since,
|
||||
);
|
||||
let candidate = output::resolve_output(
|
||||
settings,
|
||||
self.output_caps,
|
||||
self.reading,
|
||||
reading,
|
||||
self.output.frame,
|
||||
self.surface.is_some() || self.offscreen.is_some(),
|
||||
);
|
||||
@@ -269,24 +378,24 @@ impl Renderer {
|
||||
let (watch, now) =
|
||||
DisplayWatch::new(&self.window, self.surface.as_deref(), &self.adapter);
|
||||
self.display = Some(watch);
|
||||
self.output_caps.hdr = self.surface_offer().unwrap_or(self.output_caps.hdr);
|
||||
let offer = offer(self.surface.as_deref(), &self.adapter);
|
||||
self.output_caps.hdr = offer.unwrap_or(self.output_caps.hdr);
|
||||
self.reading = now;
|
||||
self.display_fresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// What the window's surface offers now (`None` offscreen): Vulkan's offered formats can
|
||||
/// change with desktop HDR or the window's output, and a display can offer the other
|
||||
/// encoding.
|
||||
fn surface_offer(&self) -> Option<Option<hdr::Output>> {
|
||||
let surface = self.surface.as_ref()?;
|
||||
Some(hdr::output(&surface.get_capabilities(&self.adapter)))
|
||||
/// The swapchain's configuration: `config` (what every pipeline draws in), or
|
||||
/// HDR10 or scRGB while HDR output is on.
|
||||
pub(super) fn surface_config(&self) -> wgpu::SurfaceConfiguration {
|
||||
surface_config(&self.config, self.hdr.as_ref().map(|hdr| hdr.output))
|
||||
}
|
||||
|
||||
/// After a new window surface: what it offers, and an output that failed on the old one
|
||||
/// may be tried again. The settings apply again.
|
||||
pub(super) fn surface_recreated(&mut self) {
|
||||
self.output_caps.hdr = self.surface_offer().unwrap_or(self.output_caps.hdr);
|
||||
let offer = offer(self.surface.as_deref(), &self.adapter);
|
||||
self.output_caps.hdr = offer.unwrap_or(self.output_caps.hdr);
|
||||
self.display_fresh = true;
|
||||
self.output_rejected = None;
|
||||
}
|
||||
@@ -295,22 +404,28 @@ impl Renderer {
|
||||
/// (another output, the player recalibrating the desktop, desktop HDR offering the other
|
||||
/// encoding): the settings' Auto values and the output follow it then, so apply them
|
||||
/// again. Each due poll reads the surface's capabilities as well, even when the display
|
||||
/// reports the same.
|
||||
/// reports the same. So does the end of Auto's grace (`auto_grace`), with or without a
|
||||
/// poll or an event then.
|
||||
pub fn display_changed(&mut self) -> bool {
|
||||
super::flush_display_log();
|
||||
if std::mem::take(&mut self.display_fresh) {
|
||||
return true;
|
||||
}
|
||||
let Some(watch) = self.display.as_mut() else {
|
||||
return false;
|
||||
};
|
||||
self.read_display(Instant::now())
|
||||
}
|
||||
|
||||
/// The display read where a poll is due or Auto's grace is over (`poll_display`).
|
||||
fn read_display(&mut self, now: Instant) -> bool {
|
||||
let (surface, adapter) = (self.surface.as_deref(), &self.adapter);
|
||||
let read = || DisplayReading::read(surface, adapter);
|
||||
let Some(now) = watch.poll(self.reading, std::time::Instant::now(), read) else {
|
||||
return false;
|
||||
};
|
||||
let offer = self.surface_offer();
|
||||
observe(&mut self.reading, &mut self.output_caps, now, offer)
|
||||
poll_display(
|
||||
self.display.as_mut(),
|
||||
&mut self.reading,
|
||||
&mut self.output_caps,
|
||||
self.auto_off_since,
|
||||
now,
|
||||
|| DisplayReading::read(surface, adapter),
|
||||
|| offer(surface, adapter),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,7 +550,8 @@ mod tests {
|
||||
paper_white: 250,
|
||||
peak: 600,
|
||||
});
|
||||
settings.hdr_ui_brightness = 60;
|
||||
// 150 nits under the reported paper white of 250: 0.6 of it.
|
||||
settings.hdr_ui_nits = 150;
|
||||
let mut swapchain = Swapchain::default();
|
||||
let next = candidate(&settings, caps, reading, &applied);
|
||||
let published = commit(&mut swapchain, &applied, next, caps, &mut None);
|
||||
@@ -529,4 +645,298 @@ mod tests {
|
||||
commit(&mut swapchain, &pq, next, caps, &mut rejected);
|
||||
assert_eq!(swapchain.asked.len(), 4);
|
||||
}
|
||||
|
||||
/// A window in Auto presenting HDR10 at 400/1000 nits on the layered frame, followed on
|
||||
/// fake time as the game follows a renderer each frame: `display_changed`, then
|
||||
/// `update_output` where it says so.
|
||||
struct Auto {
|
||||
settings: Graphics,
|
||||
start: Instant,
|
||||
watch: DisplayWatch,
|
||||
reading: DisplayReading,
|
||||
caps: OutputCapabilities,
|
||||
applied: EffectiveOutput,
|
||||
since: Option<Instant>,
|
||||
swapchain: Swapchain,
|
||||
/// What the system reports when it is read, and when (ms) it was.
|
||||
report: DisplayReading,
|
||||
reads: Vec<u64>,
|
||||
}
|
||||
impl Auto {
|
||||
/// `polled`: the system is read every `DISPLAY_POLL` from 0, else it sends events
|
||||
/// (`event`), as on Wayland.
|
||||
fn new(polled: bool) -> Self {
|
||||
let settings = Graphics {
|
||||
hdr: HdrMode::Auto,
|
||||
..Graphics::default()
|
||||
};
|
||||
let (caps, reading) = window(Some(Pq), Some(true));
|
||||
let applied = snapshot(&settings, NO_PACK, caps, reading);
|
||||
assert!(applied.encoding == Some(Pq) && applied.frame.hud_layer);
|
||||
let start = Instant::now();
|
||||
Self {
|
||||
settings,
|
||||
start,
|
||||
watch: DisplayWatch {
|
||||
#[cfg(target_os = "linux")]
|
||||
wayland: None,
|
||||
polled: polled.then_some(start),
|
||||
},
|
||||
reading,
|
||||
caps,
|
||||
applied,
|
||||
since: None,
|
||||
swapchain: Swapchain::default(),
|
||||
report: reading,
|
||||
reads: Vec::new(),
|
||||
}
|
||||
}
|
||||
/// A frame at `ms`.
|
||||
fn frame(&mut self, ms: u64) {
|
||||
if self.read_display(ms) {
|
||||
self.update(ms);
|
||||
}
|
||||
}
|
||||
/// `Renderer::read_display` at `ms`.
|
||||
fn read_display(&mut self, ms: u64) -> bool {
|
||||
let now = self.start + Duration::from_millis(ms);
|
||||
let (report, offer, reads) = (self.report, Some(self.caps.hdr), &mut self.reads);
|
||||
let read = || {
|
||||
reads.push(ms);
|
||||
report
|
||||
};
|
||||
let (reading, caps) = (&mut self.reading, &mut self.caps);
|
||||
poll_display(
|
||||
Some(&mut self.watch),
|
||||
reading,
|
||||
caps,
|
||||
self.since,
|
||||
now,
|
||||
read,
|
||||
|| offer,
|
||||
)
|
||||
}
|
||||
/// Frames from `from` to `to` ms, every 10 ms.
|
||||
fn frames(&mut self, from: u64, to: u64) {
|
||||
for ms in (from..=to).step_by(10) {
|
||||
self.frame(ms);
|
||||
}
|
||||
}
|
||||
/// What the system reports from `ms` on: HDR `hdr`, with no luminance unless it is
|
||||
/// HDR, at 300/800 nits then.
|
||||
fn reports(&mut self, hdr: Option<bool>, offer: Option<hdr::Output>) {
|
||||
self.report = DisplayReading {
|
||||
luminance: (hdr == Some(true)).then_some(Reported {
|
||||
paper_white: 300,
|
||||
peak: 800,
|
||||
}),
|
||||
hdr,
|
||||
};
|
||||
self.caps.hdr = offer;
|
||||
}
|
||||
/// The system's event at `ms`, with what it now `reports`.
|
||||
fn event(&mut self, ms: u64, hdr: Option<bool>, offer: Option<hdr::Output>) {
|
||||
self.reports(hdr, offer);
|
||||
self.reading = self.report;
|
||||
self.update(ms);
|
||||
}
|
||||
/// `update_output` at `ms`, in its order.
|
||||
fn update(&mut self, ms: u64) {
|
||||
let now = self.start + Duration::from_millis(ms);
|
||||
if grace_over(self.since, now) {
|
||||
self.read_display(ms);
|
||||
}
|
||||
let applied = &self.applied;
|
||||
let reading = auto_grace(
|
||||
now,
|
||||
self.settings.hdr,
|
||||
self.caps.hdr,
|
||||
self.reading,
|
||||
applied,
|
||||
&mut self.since,
|
||||
);
|
||||
let next = candidate(&self.settings, self.caps, reading, applied);
|
||||
self.applied = commit(&mut self.swapchain, applied, next, self.caps, &mut None);
|
||||
// While HDR stays on, the frame the game asks for (`Renderer::requested_frame`) is
|
||||
// this one: no new renderer.
|
||||
let reading = graced(self.since, self.reading, &self.applied);
|
||||
let frame = output::resolve_frame(
|
||||
&self.settings,
|
||||
NO_PACK,
|
||||
self.caps,
|
||||
reading,
|
||||
wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||
);
|
||||
assert_eq!(
|
||||
frame == self.applied.frame,
|
||||
self.applied.hdr_on(),
|
||||
"{ms} ms"
|
||||
);
|
||||
}
|
||||
fn presented(&self) -> Vec<Option<hdr::Output>> {
|
||||
self.swapchain.asked.iter().map(|a| a.0).collect()
|
||||
}
|
||||
}
|
||||
|
||||
/// The display's report flickers off and back, false or unknown: HDR stays on, nothing
|
||||
/// is presented again, and the shader `Frame`, what the settings show as active and the
|
||||
/// nits stay as they were applied, even while the report says nothing of them.
|
||||
#[test]
|
||||
fn a_report_that_flickers_off_and_back_swaps_nothing() {
|
||||
for lost in [Some(false), None] {
|
||||
let mut auto = Auto::new(false);
|
||||
let before = auto.applied;
|
||||
auto.event(0, Some(true), Some(Pq));
|
||||
auto.frames(0, 90);
|
||||
let fresh = auto.applied;
|
||||
assert_eq!(fresh.nits, [300.0, 800.0, 0.0], "a positive report applies");
|
||||
auto.event(100, lost, Some(Pq));
|
||||
auto.frames(100, 390);
|
||||
assert_eq!(auto.applied, fresh, "{lost:?}");
|
||||
assert!(auto.applied.requests_hdr(HdrMode::Auto) && auto.applied.display().hdr);
|
||||
auto.event(400, Some(true), Some(Pq));
|
||||
auto.frames(400, 1500);
|
||||
assert_eq!((auto.applied, auto.since), (fresh, None), "{lost:?}");
|
||||
assert!(auto.presented().is_empty(), "{lost:?}");
|
||||
assert_eq!(auto.applied.frame, before.frame);
|
||||
}
|
||||
}
|
||||
|
||||
/// A loss held through 600 ms turns HDR off once, at 500 ms, and on an event-driven
|
||||
/// display with no event then. The same loss reported again doesn't restart the timer.
|
||||
#[test]
|
||||
fn a_loss_held_turns_hdr_off_once_at_the_deadline() {
|
||||
for lost in [Some(false), None] {
|
||||
let mut auto = Auto::new(false);
|
||||
auto.event(0, lost, Some(Pq));
|
||||
auto.frames(0, 190);
|
||||
auto.event(200, lost, Some(Pq));
|
||||
auto.frames(200, 490);
|
||||
assert_eq!(auto.applied.encoding, Some(Pq), "{lost:?}");
|
||||
auto.frame(500);
|
||||
assert_eq!(auto.applied.encoding, None, "{lost:?}");
|
||||
auto.frames(500, 3000);
|
||||
assert_eq!(auto.presented(), [None], "{lost:?}");
|
||||
assert_eq!(auto.since, None);
|
||||
}
|
||||
}
|
||||
|
||||
/// Where the system is polled, a false read by the poll that starts the timer is read
|
||||
/// again at the deadline, not two seconds after, before it counts: the display came back
|
||||
/// meanwhile, so HDR stays; where it didn't, HDR turns off then. The two-second cadence
|
||||
/// stays otherwise.
|
||||
#[test]
|
||||
fn a_polled_false_is_read_again_at_the_deadline() {
|
||||
for back in [true, false] {
|
||||
let mut auto = Auto::new(true);
|
||||
auto.frames(0, 1990);
|
||||
auto.reports(Some(false), Some(Pq));
|
||||
auto.frame(2000);
|
||||
assert_eq!(
|
||||
(auto.applied.encoding, auto.since.is_some()),
|
||||
(Some(Pq), true)
|
||||
);
|
||||
if back {
|
||||
auto.reports(Some(true), Some(Pq));
|
||||
}
|
||||
auto.frames(2010, 2490);
|
||||
assert_eq!(auto.applied.encoding, Some(Pq), "never before the deadline");
|
||||
auto.frames(2500, 4990);
|
||||
assert_eq!(auto.reads, [0, 2000, 2500, 4500], "back {back}");
|
||||
let after = if back { vec![] } else { vec![None] };
|
||||
assert_eq!(auto.presented(), after, "back {back}");
|
||||
}
|
||||
}
|
||||
|
||||
/// A settings change at the deadline, before the frame's poll (a slider, F11), reads the
|
||||
/// display before the grace ends, and the frame after reads it no more: the display came
|
||||
/// back meanwhile, so HDR stays; where it didn't, HDR turns off then, once.
|
||||
#[test]
|
||||
fn a_settings_change_at_the_deadline_reads_the_display_first() {
|
||||
for back in [true, false] {
|
||||
let mut auto = Auto::new(true);
|
||||
auto.frames(0, 1990);
|
||||
auto.reports(Some(false), Some(Pq));
|
||||
auto.frame(2000);
|
||||
if back {
|
||||
auto.reports(Some(true), Some(Pq));
|
||||
}
|
||||
auto.frames(2010, 2490);
|
||||
auto.update(2500);
|
||||
assert_eq!(auto.applied.hdr_on(), back, "back {back}");
|
||||
auto.frames(2500, 4990);
|
||||
assert_eq!(auto.reads, [0, 2000, 2500, 4500], "back {back}");
|
||||
let after = if back { vec![] } else { vec![None] };
|
||||
assert_eq!(auto.presented(), after, "back {back}");
|
||||
}
|
||||
}
|
||||
|
||||
/// A positive report clears the timer: a later loss has its own 500 ms.
|
||||
#[test]
|
||||
fn a_positive_report_clears_the_timer() {
|
||||
let mut auto = Auto::new(false);
|
||||
auto.event(100, Some(false), Some(Pq));
|
||||
auto.event(300, Some(true), Some(Pq));
|
||||
auto.event(700, Some(false), Some(Pq));
|
||||
auto.frames(700, 1190);
|
||||
assert_eq!(auto.applied.encoding, Some(Pq));
|
||||
auto.frame(1200);
|
||||
assert_eq!(auto.presented(), [None]);
|
||||
}
|
||||
|
||||
/// Off acts at once, and On or Off clear the timer: Auto again starts it anew.
|
||||
#[test]
|
||||
fn off_and_on_take_no_grace() {
|
||||
let mut auto = Auto::new(false);
|
||||
auto.event(100, Some(false), Some(Pq));
|
||||
auto.settings.hdr = HdrMode::Off;
|
||||
auto.update(200);
|
||||
assert_eq!((auto.presented(), auto.since), (vec![None], None));
|
||||
let mut auto = Auto::new(false);
|
||||
auto.event(100, Some(false), Some(Pq));
|
||||
auto.settings.hdr = HdrMode::On;
|
||||
auto.update(200);
|
||||
assert_eq!((auto.applied.encoding, auto.since), (Some(Pq), None));
|
||||
auto.settings.hdr = HdrMode::Auto;
|
||||
auto.update(300);
|
||||
auto.frames(300, 790);
|
||||
assert_eq!(auto.applied.encoding, Some(Pq));
|
||||
auto.frame(800);
|
||||
assert_eq!(auto.presented(), [None]);
|
||||
}
|
||||
|
||||
/// The surface no longer offering the encoding presented ends the grace at once: SDR
|
||||
/// without a report, the other encoding with one.
|
||||
#[test]
|
||||
fn an_encoding_no_longer_offered_is_not_kept() {
|
||||
for offer in [None, Some(ScRgb)] {
|
||||
let mut auto = Auto::new(false);
|
||||
auto.event(100, Some(false), Some(Pq));
|
||||
auto.event(200, Some(false), offer);
|
||||
assert_eq!((auto.presented(), auto.since), (vec![None], None));
|
||||
let mut auto = Auto::new(false);
|
||||
auto.event(100, None, offer);
|
||||
assert_eq!(auto.presented(), [None], "{offer:?}");
|
||||
}
|
||||
let mut auto = Auto::new(false);
|
||||
auto.event(100, Some(false), Some(Pq));
|
||||
auto.event(200, Some(true), Some(ScRgb));
|
||||
assert_eq!(auto.presented(), [Some(ScRgb)]);
|
||||
}
|
||||
|
||||
/// Two windows' timers run apart.
|
||||
#[test]
|
||||
fn two_renderers_keep_their_own_timer() {
|
||||
let (mut a, mut b) = (Auto::new(false), Auto::new(false));
|
||||
b.start = a.start;
|
||||
a.event(100, Some(false), Some(Pq));
|
||||
b.event(300, Some(false), Some(Pq));
|
||||
a.event(400, Some(true), Some(Pq));
|
||||
for ms in (300..=900).step_by(10) {
|
||||
a.frame(ms);
|
||||
b.frame(ms);
|
||||
assert_eq!(b.applied.hdr_on(), ms < 800, "{ms} ms");
|
||||
}
|
||||
assert_eq!((a.presented(), b.presented()), (vec![], vec![None]));
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,10 @@ mod sky_disc_blend_tests;
|
||||
#[cfg(test)]
|
||||
mod undrawn_terrain_tests;
|
||||
|
||||
mod image_formats;
|
||||
use image_formats::{image_format, storage_formats_of};
|
||||
#[cfg(test)]
|
||||
mod full_outputs_tests;
|
||||
#[cfg(test)]
|
||||
mod shadow_faces_tests;
|
||||
|
||||
@@ -1826,98 +1830,6 @@ fn bindings(
|
||||
Some((entries, samplers, slots, reads, shadow_reads, images))
|
||||
}
|
||||
|
||||
/// Makes each storage image of `module` in group 0 declare the format its layout entry binds:
|
||||
/// a `layout(r11f_g11f_b10f)` image whose texture is the `RGBA16F` stand-in (`bindings`).
|
||||
fn storage_formats_of(module: &mut naga::Module, entries: &[wgpu::BindGroupLayoutEntry]) {
|
||||
let globals: Vec<_> = module.global_variables.iter().map(|(h, _)| h).collect();
|
||||
for handle in globals {
|
||||
let var = &module.global_variables[handle];
|
||||
let Some(naga::ResourceBinding { group: 0, binding }) = var.binding else {
|
||||
continue;
|
||||
};
|
||||
let naga::TypeInner::Image {
|
||||
dim,
|
||||
arrayed,
|
||||
class: naga::ImageClass::Storage { format, access },
|
||||
} = module.types[var.ty].inner
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let bound = entries.iter().find_map(|e| match e.ty {
|
||||
wgpu::BindingType::StorageTexture { format, .. } if e.binding == binding => {
|
||||
Some(format)
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
if format == naga::StorageFormat::Rg11b10Ufloat
|
||||
&& bound == Some(wgpu::TextureFormat::Rgba16Float)
|
||||
{
|
||||
let ty = module.types.insert(
|
||||
naga::Type {
|
||||
name: module.types[var.ty].name.clone(),
|
||||
inner: naga::TypeInner::Image {
|
||||
dim,
|
||||
arrayed,
|
||||
class: naga::ImageClass::Storage {
|
||||
format: naga::StorageFormat::Rgba16Float,
|
||||
access,
|
||||
},
|
||||
},
|
||||
},
|
||||
naga::Span::UNDEFINED,
|
||||
);
|
||||
module.global_variables[handle].ty = ty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The wgpu format of an image's format qualifier.
|
||||
fn image_format(qualifier: &str) -> Option<wgpu::TextureFormat> {
|
||||
use wgpu::TextureFormat as T;
|
||||
Some(match qualifier {
|
||||
"rgba32f" => T::Rgba32Float,
|
||||
"rgba16f" => T::Rgba16Float,
|
||||
"rg32f" => T::Rg32Float,
|
||||
"rg16f" => T::Rg16Float,
|
||||
"r11f_g11f_b10f" => T::Rg11b10Ufloat,
|
||||
"r32f" => T::R32Float,
|
||||
"r16f" => T::R16Float,
|
||||
"rgba16" => T::Rgba16Unorm,
|
||||
"rgb10_a2" => T::Rgb10a2Unorm,
|
||||
"rgba8" => T::Rgba8Unorm,
|
||||
"rg16" => T::Rg16Unorm,
|
||||
"rg8" => T::Rg8Unorm,
|
||||
"r16" => T::R16Unorm,
|
||||
"r8" => T::R8Unorm,
|
||||
"rgba16_snorm" => T::Rgba16Snorm,
|
||||
"rgba8_snorm" => T::Rgba8Snorm,
|
||||
"rg16_snorm" => T::Rg16Snorm,
|
||||
"rg8_snorm" => T::Rg8Snorm,
|
||||
"r16_snorm" => T::R16Snorm,
|
||||
"r8_snorm" => T::R8Snorm,
|
||||
"rgba32i" => T::Rgba32Sint,
|
||||
"rgba16i" => T::Rgba16Sint,
|
||||
"rgba8i" => T::Rgba8Sint,
|
||||
"rg32i" => T::Rg32Sint,
|
||||
"rg16i" => T::Rg16Sint,
|
||||
"rg8i" => T::Rg8Sint,
|
||||
"r32i" => T::R32Sint,
|
||||
"r16i" => T::R16Sint,
|
||||
"r8i" => T::R8Sint,
|
||||
"rgba32ui" => T::Rgba32Uint,
|
||||
"rgba16ui" => T::Rgba16Uint,
|
||||
"rgb10_a2ui" => T::Rgb10a2Uint,
|
||||
"rgba8ui" => T::Rgba8Uint,
|
||||
"rg32ui" => T::Rg32Uint,
|
||||
"rg16ui" => T::Rg16Uint,
|
||||
"rg8ui" => T::Rg8Uint,
|
||||
"r32ui" => T::R32Uint,
|
||||
"r16ui" => T::R16Uint,
|
||||
"r8ui" => T::R8Uint,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
/// The value slot of the pack's custom uniform `name` for a program declaring it as GLSL type
|
||||
/// `ty`: after the frame's uniforms, in the order of `custom` (each with the type
|
||||
/// `shaders.properties` gives it). A `float`, `int`, `vec2`, `vec3` or `vec4` custom uniform
|
||||
@@ -2805,10 +2717,21 @@ impl PackPost {
|
||||
.shadow
|
||||
.zip(shadow_geometry.as_ref())
|
||||
.and_then(|(p, g)| build(p, Some(g)));
|
||||
// A GPU that refuses translucent terrain's program with the boats' water patches gets it
|
||||
// without them (`Post::shadow_water_plain`), rather than no translucent shadows at all.
|
||||
let mut plain = post.shadow_water_plain;
|
||||
let shadow_water = post
|
||||
.shadow_water
|
||||
.zip(shadow_geometry.as_ref())
|
||||
.and_then(|(p, g)| build(p, Some(g)));
|
||||
let unpatched = shadow_water.is_none().then(|| plain.take()).flatten();
|
||||
let unpatched_name = unpatched.as_ref().map(|p| p.name.clone());
|
||||
let shadow_water = shadow_water.or_else(|| {
|
||||
unpatched
|
||||
.zip(shadow_geometry.as_ref())
|
||||
.and_then(|(p, g)| build(p, Some(g)))
|
||||
});
|
||||
let water_unpatched = unpatched_name.filter(|_| shadow_water.is_some());
|
||||
let (hides_sky, hides_celestial) = (post.sky.is_some(), post.sky_textured.is_some());
|
||||
let sky = (post.sky.is_some() || post.sky_textured.is_some()).then(|| {
|
||||
let geometry = PackSky::new(device);
|
||||
@@ -3365,6 +3288,17 @@ impl PackPost {
|
||||
let white = [255u8; 4];
|
||||
let black = [0u8; 4];
|
||||
let flat_normal = [128u8, 128, 255, 255];
|
||||
// Said as what it is, not as a program skipped.
|
||||
if let Some(name) = water_unpatched {
|
||||
let skipped = format!("{name}: skipped: ");
|
||||
if let Some(n) = notes.iter_mut().rev().find(|n| n.starts_with(&skipped)) {
|
||||
*n = format!(
|
||||
"{name}: translucent terrain without the boats' water patches, as the GPU \
|
||||
refused it with them ({})",
|
||||
&n[skipped.len()..]
|
||||
);
|
||||
}
|
||||
}
|
||||
let jobs = (pack.jobs.as_ref())
|
||||
.map(std::cell::RefCell::take)
|
||||
.unwrap_or_default();
|
||||
|
||||
@@ -602,7 +602,7 @@ pub(super) fn fixture_frame(hud: &HudBatch) -> Frame<'_> {
|
||||
outline: Vec::new(),
|
||||
outline_after_terrain: false,
|
||||
outline_high_contrast: false,
|
||||
pvp: Default::default(),
|
||||
look: Default::default(),
|
||||
debug_lines: &[],
|
||||
debug_lines_on_top: &[],
|
||||
debug_crosshair: &[],
|
||||
|
||||
@@ -440,7 +440,7 @@ fn fixture_frame(hud: &HudBatch) -> Frame<'_> {
|
||||
outline: Vec::new(),
|
||||
outline_after_terrain: false,
|
||||
outline_high_contrast: false,
|
||||
pvp: Default::default(),
|
||||
look: Default::default(),
|
||||
debug_lines: &[],
|
||||
debug_lines_on_top: &[],
|
||||
debug_crosshair: &[],
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
//! A shadow program writing as many vertex outputs as the GPU takes leaves no room for the boats'
|
||||
//! water patches (`GbuffersInputs::water_patches`, one output more): translucent terrain gets
|
||||
//! the program without them, not no shadow program. The programs here are original.
|
||||
use super::destination_tests::Fixture;
|
||||
use super::*;
|
||||
use std::io::{Cursor, Write};
|
||||
|
||||
fn pack(outputs: u32) -> Post {
|
||||
let mut zip = zip::ZipWriter::new(Cursor::new(Vec::new()));
|
||||
let mut add = |name: &str, source: &str| {
|
||||
zip.start_file(
|
||||
format!("shaders/{name}"),
|
||||
zip::write::SimpleFileOptions::default(),
|
||||
)
|
||||
.unwrap();
|
||||
zip.write_all(source.as_bytes()).unwrap();
|
||||
};
|
||||
let declared: String = (0..outputs)
|
||||
.map(|i| format!("varying vec4 v{i};\n"))
|
||||
.collect();
|
||||
let written: String = (0..outputs).map(|i| format!("v{i}=vec4({i}.0);")).collect();
|
||||
let read: String = (0..outputs).map(|i| format!("+v{i}")).collect();
|
||||
add(
|
||||
"shadow.vsh",
|
||||
&format!(
|
||||
"#version 120\n{declared}void main() {{ gl_Position=vec4(gl_Vertex.xy,0.5,1.0); {written} }}\n"
|
||||
),
|
||||
);
|
||||
add(
|
||||
"shadow.fsh",
|
||||
&format!("#version 120\n{declared}void main() {{ gl_FragData[0]=vec4(0.0){read}; }}\n"),
|
||||
);
|
||||
add(
|
||||
"final.vsh",
|
||||
"#version 120\nvarying vec2 uv;\nvoid main() { uv=gl_MultiTexCoord0.xy; gl_Position=ftransform(); }\n",
|
||||
);
|
||||
add(
|
||||
"final.fsh",
|
||||
"#version 120\nconst int shadowMapResolution=16;\nuniform sampler2D shadowcolor0;\n\
|
||||
varying vec2 uv;\nvoid main() { gl_FragColor=texture2D(shadowcolor0,uv); }\n",
|
||||
);
|
||||
let pack = horizon_shaders::Pack::from_zip_bytes(
|
||||
"original-full-outputs",
|
||||
zip.finish().unwrap().into_inner(),
|
||||
)
|
||||
.unwrap();
|
||||
let mut macros = horizon_shaders::Macros::standard();
|
||||
let (properties, _) = horizon_shaders::read_properties(&pack, &mut macros);
|
||||
let inputs = horizon_shaders::GameInputs {
|
||||
terrain: Some(horizon_shaders::GbuffersInputs {
|
||||
item_id_declared: false,
|
||||
far_depth: false,
|
||||
paged_maps: false,
|
||||
water_mask: false,
|
||||
water_patches: false,
|
||||
declarations: "layout(location=0)in vec3 fixture_position;\n".into(),
|
||||
body: "hz_Vertex=vec4(fixture_position,1.0);hz_Color=vec4(1.0);\
|
||||
hz_MultiTexCoord0=vec4(0.0);hz_MultiTexCoord1=vec4(240.0);\
|
||||
hz_MultiTexCoord2=vec4(240.0);hz_Normal=vec3(0.0,0.0,1.0);\n"
|
||||
.into(),
|
||||
attributes: vec![],
|
||||
after: String::new(),
|
||||
alpha_test: None,
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
horizon_shaders::load_post(&pack, "", &properties, ¯os, &inputs)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_shadow_program_with_every_output_drops_the_boats_patches_not_its_water() {
|
||||
let Some(gpu) = Fixture::new() else { return };
|
||||
const ATTRS: [wgpu::VertexAttribute; 1] = wgpu::vertex_attr_array![0=>Float32x3];
|
||||
let layouts = [Some(wgpu::VertexBufferLayout {
|
||||
array_stride: 12,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &ATTRS,
|
||||
})];
|
||||
let geometry = || {
|
||||
Some(Geometry {
|
||||
material_maps: false,
|
||||
buffers: &layouts,
|
||||
table: None,
|
||||
depth_write: true,
|
||||
atlas: None,
|
||||
ids: None,
|
||||
cull: true,
|
||||
})
|
||||
};
|
||||
let outputs = gpu.device.limits().max_inter_stage_shader_variables;
|
||||
let post = gpu.build_with_terrain(pack(outputs), geometry());
|
||||
assert!(post.has_shadow(), "{:?}", post.notes);
|
||||
assert!(post.shadow_water.is_some(), "{:?}", post.notes);
|
||||
assert!(
|
||||
post.notes
|
||||
.iter()
|
||||
.any(|n| n.contains("without the boats' water patches")),
|
||||
"{:?}",
|
||||
post.notes
|
||||
);
|
||||
// With room for them, the patches stay and nothing is said.
|
||||
let post = gpu.build_with_terrain(pack(outputs - 1), geometry());
|
||||
assert!(post.shadow_water.is_some(), "{:?}", post.notes);
|
||||
assert!(
|
||||
!post.notes.iter().any(|n| n.contains("water patches")),
|
||||
"{:?}",
|
||||
post.notes
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
//! Image formats: a storage image's format qualifier as wgpu's, and the stand-in a module's
|
||||
//! storage images declare.
|
||||
|
||||
/// Makes each storage image of `module` in group 0 declare the format its layout entry binds:
|
||||
/// a `layout(r11f_g11f_b10f)` image whose texture is the `RGBA16F` stand-in (`bindings`).
|
||||
pub(super) fn storage_formats_of(
|
||||
module: &mut naga::Module,
|
||||
entries: &[wgpu::BindGroupLayoutEntry],
|
||||
) {
|
||||
let globals: Vec<_> = module.global_variables.iter().map(|(h, _)| h).collect();
|
||||
for handle in globals {
|
||||
let var = &module.global_variables[handle];
|
||||
let Some(naga::ResourceBinding { group: 0, binding }) = var.binding else {
|
||||
continue;
|
||||
};
|
||||
let naga::TypeInner::Image {
|
||||
dim,
|
||||
arrayed,
|
||||
class: naga::ImageClass::Storage { format, access },
|
||||
} = module.types[var.ty].inner
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let bound = entries.iter().find_map(|e| match e.ty {
|
||||
wgpu::BindingType::StorageTexture { format, .. } if e.binding == binding => {
|
||||
Some(format)
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
if format == naga::StorageFormat::Rg11b10Ufloat
|
||||
&& bound == Some(wgpu::TextureFormat::Rgba16Float)
|
||||
{
|
||||
let ty = module.types.insert(
|
||||
naga::Type {
|
||||
name: module.types[var.ty].name.clone(),
|
||||
inner: naga::TypeInner::Image {
|
||||
dim,
|
||||
arrayed,
|
||||
class: naga::ImageClass::Storage {
|
||||
format: naga::StorageFormat::Rgba16Float,
|
||||
access,
|
||||
},
|
||||
},
|
||||
},
|
||||
naga::Span::UNDEFINED,
|
||||
);
|
||||
module.global_variables[handle].ty = ty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The wgpu format of an image's format qualifier.
|
||||
pub(super) fn image_format(qualifier: &str) -> Option<wgpu::TextureFormat> {
|
||||
use wgpu::TextureFormat as T;
|
||||
Some(match qualifier {
|
||||
"rgba32f" => T::Rgba32Float,
|
||||
"rgba16f" => T::Rgba16Float,
|
||||
"rg32f" => T::Rg32Float,
|
||||
"rg16f" => T::Rg16Float,
|
||||
"r11f_g11f_b10f" => T::Rg11b10Ufloat,
|
||||
"r32f" => T::R32Float,
|
||||
"r16f" => T::R16Float,
|
||||
"rgba16" => T::Rgba16Unorm,
|
||||
"rgb10_a2" => T::Rgb10a2Unorm,
|
||||
"rgba8" => T::Rgba8Unorm,
|
||||
"rg16" => T::Rg16Unorm,
|
||||
"rg8" => T::Rg8Unorm,
|
||||
"r16" => T::R16Unorm,
|
||||
"r8" => T::R8Unorm,
|
||||
"rgba16_snorm" => T::Rgba16Snorm,
|
||||
"rgba8_snorm" => T::Rgba8Snorm,
|
||||
"rg16_snorm" => T::Rg16Snorm,
|
||||
"rg8_snorm" => T::Rg8Snorm,
|
||||
"r16_snorm" => T::R16Snorm,
|
||||
"r8_snorm" => T::R8Snorm,
|
||||
"rgba32i" => T::Rgba32Sint,
|
||||
"rgba16i" => T::Rgba16Sint,
|
||||
"rgba8i" => T::Rgba8Sint,
|
||||
"rg32i" => T::Rg32Sint,
|
||||
"rg16i" => T::Rg16Sint,
|
||||
"rg8i" => T::Rg8Sint,
|
||||
"r32i" => T::R32Sint,
|
||||
"r16i" => T::R16Sint,
|
||||
"r8i" => T::R8Sint,
|
||||
"rgba32ui" => T::Rgba32Uint,
|
||||
"rgba16ui" => T::Rgba16Uint,
|
||||
"rgb10_a2ui" => T::Rgb10a2Uint,
|
||||
"rgba8ui" => T::Rgba8Uint,
|
||||
"rg32ui" => T::Rg32Uint,
|
||||
"rg16ui" => T::Rg16Uint,
|
||||
"rg8ui" => T::Rg8Uint,
|
||||
"r32ui" => T::R32Uint,
|
||||
"r16ui" => T::R16Uint,
|
||||
"r8ui" => T::R8Uint,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@@ -409,7 +409,7 @@ fn frame(hud: &HudBatch) -> Frame<'_> {
|
||||
outline: Vec::new(),
|
||||
outline_after_terrain: false,
|
||||
outline_high_contrast: false,
|
||||
pvp: Default::default(),
|
||||
look: Default::default(),
|
||||
debug_lines: &[],
|
||||
debug_lines_on_top: &[],
|
||||
debug_crosshair: &[],
|
||||
|
||||
@@ -2664,7 +2664,7 @@ pub(super) mod initial_history_tests {
|
||||
outline: Vec::new(),
|
||||
outline_after_terrain: false,
|
||||
outline_high_contrast: false,
|
||||
pvp: Default::default(),
|
||||
look: Default::default(),
|
||||
debug_lines: &[],
|
||||
debug_lines_on_top: &[],
|
||||
debug_crosshair: &[],
|
||||
|
||||
@@ -52,6 +52,23 @@ pub fn peak_step_of(nits: f32) -> f32 {
|
||||
};
|
||||
step.clamp(0.0, PEAK_STEPS as f32)
|
||||
}
|
||||
/// The steps of Paper White's and UI Brightness's scale: Auto (0), then 10 to 480 nits by 10.
|
||||
pub const NITS_STEPS: u32 = 48;
|
||||
/// Paper White's or UI Brightness's setting at slider position `v`, 0 to 1 ([`NITS_STEPS`]).
|
||||
pub fn nits_at(v: f32) -> u32 {
|
||||
(v * NITS_STEPS as f32).round() as u32 * 10
|
||||
}
|
||||
/// Where a Paper White or UI Brightness setting sits on its slider, 0 to 1.
|
||||
pub fn nits_position(nits: u32) -> f32 {
|
||||
nits as f32 / (NITS_STEPS * 10) as f32
|
||||
}
|
||||
/// A saved Paper White or UI Brightness: Auto (0), or 10 to 480 nits.
|
||||
fn nits_setting(nits: u32) -> u32 {
|
||||
match nits {
|
||||
0 => 0,
|
||||
n => n.clamp(10, 480),
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple-level presets. `Custom` leaves every option as the player set it.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||
@@ -504,8 +521,6 @@ pub fn reduced_far_detail_suggested() -> bool {
|
||||
REDUCED_SUGGESTED.load(std::sync::atomic::Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// The name the options screen waits on to bind `Graphics::hdr_key`.
|
||||
pub const HDR_KEY: &str = "horizon.hdrSettings";
|
||||
/// The Screenshot Quality choices, times the game's resolution.
|
||||
pub const SCREENSHOT_QUALITIES: [u32; 4] = [1, 2, 4, 8];
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||
@@ -815,14 +830,12 @@ pub struct Graphics {
|
||||
/// HDR black level: the display's darkest black, in hundredths of a nit; 0, the default,
|
||||
/// lifts nothing. Shadows are lifted onto it, and the HDR metadata says it.
|
||||
pub hdr_black_level: u32,
|
||||
/// HDR brightness of the HUD and menus, in percent of paper white (25..=100); the
|
||||
/// first-person hand stays at the world's.
|
||||
pub hdr_ui_brightness: u32,
|
||||
/// HDR brightness of the HUD and menus, in nits; 0 is Auto: at paper white
|
||||
/// ([`Graphics::ui_nits`]). The first-person hand stays at the world's.
|
||||
pub hdr_ui_nits: u32,
|
||||
/// HDR Lighting: Horizon's own HDR look, light sources, the sun and sunlight above paper
|
||||
/// white. Off, HDR output shows the same picture as SDR, for shader packs or the vanilla look.
|
||||
pub hdr_lighting: bool,
|
||||
/// A vanilla key name (`HDR_KEY`): opens HDR's settings from the game. Unbound by default.
|
||||
pub hdr_key: String,
|
||||
/// The graphics driver whose last start ended before HDR output showed a frame (the
|
||||
/// marker found, [`HDR_MARKER`]): a window on it stays SDR whatever the mode, until the
|
||||
/// mode is changed or the window starts on another driver ([`Graphics::hdr_held`]).
|
||||
@@ -900,9 +913,8 @@ impl Default for Graphics {
|
||||
hdr_paper_white: 0,
|
||||
hdr_peak: 0,
|
||||
hdr_black_level: 0,
|
||||
hdr_ui_brightness: 100,
|
||||
hdr_ui_nits: 0,
|
||||
hdr_lighting: true,
|
||||
hdr_key: "key.keyboard.unknown".into(),
|
||||
hdr_failed_start: None,
|
||||
battery: false,
|
||||
shadow_cache: false,
|
||||
@@ -975,6 +987,8 @@ impl Graphics {
|
||||
}
|
||||
pub fn parse(text: &str) -> Self {
|
||||
let mut g = Self::default();
|
||||
// UI Brightness: `hdrUiNits`, else an older file's share of Paper White.
|
||||
let (mut ui_nits, mut ui_share) = (None, None);
|
||||
for line in text.lines() {
|
||||
let Some((key, value)) = line.split_once(':') else {
|
||||
continue;
|
||||
@@ -1064,12 +1078,9 @@ impl Graphics {
|
||||
"frameGeneration" => g.frame_generation = FrameGeneration::parse(value),
|
||||
"hdr" => g.hdr = HdrMode::parse(value, g.hdr),
|
||||
"hdrLighting" => g.hdr_lighting = flag(g.hdr_lighting),
|
||||
"hdrPaperWhite" => {
|
||||
g.hdr_paper_white = match number(g.hdr_paper_white) {
|
||||
0 => 0,
|
||||
n => n.clamp(10, 480),
|
||||
}
|
||||
}
|
||||
"hdrPaperWhite" => g.hdr_paper_white = nits_setting(number(g.hdr_paper_white)),
|
||||
"hdrUiNits" => ui_nits = value.parse().ok().map(nits_setting),
|
||||
"hdrUiBrightness" => ui_share = value.parse::<u32>().ok(),
|
||||
"hdrPeak" => {
|
||||
g.hdr_peak = match number(g.hdr_peak) {
|
||||
0 => 0,
|
||||
@@ -1077,10 +1088,6 @@ impl Graphics {
|
||||
}
|
||||
}
|
||||
"hdrBlackLevel" => g.hdr_black_level = number(g.hdr_black_level).min(100),
|
||||
"hdrUiBrightness" => {
|
||||
g.hdr_ui_brightness = number(g.hdr_ui_brightness).clamp(25, 100)
|
||||
}
|
||||
"hdrKey" if value.starts_with("key.") => g.hdr_key = value.to_owned(),
|
||||
"hdrFailedStart" => g.hdr_failed_start = Some(value.to_owned()),
|
||||
"batteryMode" => g.battery = flag(g.battery),
|
||||
"shadowCache" => g.shadow_cache = flag(g.shadow_cache),
|
||||
@@ -1098,11 +1105,20 @@ impl Graphics {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// The share was 25 to 100% of Paper White. 100% is Auto, and so is any share of an
|
||||
// Auto Paper White, whose nits the file doesn't hold; another share of a Paper White set
|
||||
// by hand is its nits, to the nearest step.
|
||||
g.hdr_ui_nits = ui_nits.unwrap_or(match (ui_share, g.hdr_paper_white) {
|
||||
(Some(share), paper) if share < 100 && paper != 0 => {
|
||||
((paper * share.max(25) + 500) / 1000).max(1) * 10
|
||||
}
|
||||
_ => 0,
|
||||
});
|
||||
g
|
||||
}
|
||||
pub fn serialize(&self) -> String {
|
||||
let mut text = format!(
|
||||
"preset:{}\nlodDistance:{}\nfarDetail:{}\ncaveCulling:{}\nentityCulling:{}\nentityCullingPrecheck:{}\nparticleCulling:{}\nleafCulling:{}\nopaqueIce:{}\nblockEntityCacheShulkerBoxes:{}\nblockEntityCacheSigns:{}\nblockEntityCacheDecoratedPots:{}\nblockEntityCacheBells:{}\nblockEntityCacheChests:{}\nblockEntityCacheBanners:{}\nblockEntityCacheCopperGolemStatues:{}\nchunkUpdates:{}\nuploadBudgetKiB:{}\ntextureBudgetMiB:{}\nsky:{}\nfog:{}\nweather:{}\nanimatedTextures:{}\nditherCutoutMips:{}\npresentMode:{}\nframePacing:{}\nworkers:{}\noverlay:{}\nresolutionScale:{}\nfxaa:{}\ntaa:{}\nupscaling:{}\nupscalingSharpness:{}\nscreenshotQuality:{}\nframeGeneration:{}\nhdr:{}\nhdrPaperWhite:{}\nhdrPeak:{}\nhdrBlackLevel:{}\nhdrUiBrightness:{}\nhdrLighting:{}\nhdrKey:{}\nbatteryMode:{}\nshadowCache:{}\ngraphicsApi:{}\npickedShaderPack:{}\nbatchTranslucent:{}\nhdrSmoothGradients:{}\ngpuCulling:{}\n",
|
||||
"preset:{}\nlodDistance:{}\nfarDetail:{}\ncaveCulling:{}\nentityCulling:{}\nentityCullingPrecheck:{}\nparticleCulling:{}\nleafCulling:{}\nopaqueIce:{}\nblockEntityCacheShulkerBoxes:{}\nblockEntityCacheSigns:{}\nblockEntityCacheDecoratedPots:{}\nblockEntityCacheBells:{}\nblockEntityCacheChests:{}\nblockEntityCacheBanners:{}\nblockEntityCacheCopperGolemStatues:{}\nchunkUpdates:{}\nuploadBudgetKiB:{}\ntextureBudgetMiB:{}\nsky:{}\nfog:{}\nweather:{}\nanimatedTextures:{}\nditherCutoutMips:{}\npresentMode:{}\nframePacing:{}\nworkers:{}\noverlay:{}\nresolutionScale:{}\nfxaa:{}\ntaa:{}\nupscaling:{}\nupscalingSharpness:{}\nscreenshotQuality:{}\nframeGeneration:{}\nhdr:{}\nhdrPaperWhite:{}\nhdrPeak:{}\nhdrBlackLevel:{}\nhdrUiNits:{}\nhdrLighting:{}\nbatteryMode:{}\nshadowCache:{}\ngraphicsApi:{}\npickedShaderPack:{}\nbatchTranslucent:{}\nhdrSmoothGradients:{}\ngpuCulling:{}\n",
|
||||
self.preset.name(),
|
||||
self.lod_distance,
|
||||
self.far_detail.name(),
|
||||
@@ -1149,9 +1165,8 @@ impl Graphics {
|
||||
self.hdr_paper_white,
|
||||
self.hdr_peak,
|
||||
self.hdr_black_level,
|
||||
self.hdr_ui_brightness,
|
||||
self.hdr_ui_nits,
|
||||
bool_text(self.hdr_lighting),
|
||||
self.hdr_key,
|
||||
bool_text(self.battery),
|
||||
bool_text(self.shadow_cache),
|
||||
self.api.name(),
|
||||
@@ -1166,14 +1181,6 @@ impl Graphics {
|
||||
text += &self.blue_map.serialize();
|
||||
text
|
||||
}
|
||||
/// Binds Horizon's graphics key `name` (`HDR_KEY`); false for another name.
|
||||
pub fn set_key(&mut self, name: &str, value: String) -> bool {
|
||||
match name {
|
||||
HDR_KEY => self.hdr_key = value,
|
||||
_ => return false,
|
||||
}
|
||||
true
|
||||
}
|
||||
pub fn save(&self, dir: &Path) {
|
||||
let _ = fs::write(dir.join(FILE), self.serialize());
|
||||
}
|
||||
@@ -1185,6 +1192,13 @@ impl Graphics {
|
||||
n => n,
|
||||
}
|
||||
}
|
||||
/// The HUD and menus' brightness, in nits: the player's, or on Auto paper white's.
|
||||
pub fn ui_nits(&self, reported: Option<Reported>) -> u32 {
|
||||
match self.hdr_ui_nits {
|
||||
0 => self.paper_white_nits(reported),
|
||||
n => n,
|
||||
}
|
||||
}
|
||||
/// The peak the world's highlights reach, in nits: the player's, or on Auto
|
||||
/// what the system `reported`, else 1000.
|
||||
pub fn peak_nits(&self, reported: Option<Reported>) -> u32 {
|
||||
@@ -1265,6 +1279,55 @@ pub fn apply_preset(preset: Preset, s: &mut crate::settings::Settings) {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// UI Brightness is saved in nits, 0 for Auto. An older file's share of Paper White reads
|
||||
/// as Auto at 100% or with Paper White on Auto, else as that share of it to the nearest step.
|
||||
#[test]
|
||||
fn ui_brightness_round_trips_in_nits_and_reads_older_shares() {
|
||||
for (file, nits) in [
|
||||
("", 0),
|
||||
("hdrUiNits:0\n", 0),
|
||||
("hdrUiNits:160\n", 160),
|
||||
("hdrUiNits:5\n", 10),
|
||||
("hdrUiNits:9000\n", 480),
|
||||
("hdrUiNits:x\n", 0),
|
||||
// Older files: 100% is Auto,
|
||||
("hdrPaperWhite:200\nhdrUiBrightness:100\n", 0),
|
||||
// any share of Paper White's Auto too,
|
||||
("hdrUiBrightness:60\n", 0),
|
||||
("hdrPaperWhite:0\nhdrUiBrightness:25\n", 0),
|
||||
// and another share of a Paper White set by hand is its nits.
|
||||
("hdrPaperWhite:200\nhdrUiBrightness:60\n", 120),
|
||||
("hdrUiBrightness:50\nhdrPaperWhite:203\n", 100),
|
||||
("hdrPaperWhite:250\nhdrUiBrightness:75\n", 190),
|
||||
("hdrPaperWhite:10\nhdrUiBrightness:25\n", 10),
|
||||
("hdrPaperWhite:480\nhdrUiBrightness:10\n", 120),
|
||||
// The new key wins over the old one.
|
||||
(
|
||||
"hdrPaperWhite:200\nhdrUiBrightness:60\nhdrUiNits:300\n",
|
||||
300,
|
||||
),
|
||||
("hdrUiNits:0\nhdrPaperWhite:200\nhdrUiBrightness:60\n", 0),
|
||||
] {
|
||||
let g = Graphics::parse(file);
|
||||
assert_eq!(g.hdr_ui_nits, nits, "{file}");
|
||||
let saved = g.serialize();
|
||||
assert!(!saved.contains("hdrUiBrightness"), "{file}");
|
||||
assert!(saved.contains(&format!("\nhdrUiNits:{nits}\n")), "{file}");
|
||||
assert_eq!(Graphics::parse(&saved), g, "{file}");
|
||||
}
|
||||
let mut g = Graphics::default();
|
||||
assert_eq!(g.ui_nits(None), 203);
|
||||
let reported = Some(Reported {
|
||||
paper_white: 300,
|
||||
peak: 1000,
|
||||
});
|
||||
assert_eq!(g.ui_nits(reported), 300);
|
||||
g.hdr_paper_white = 120;
|
||||
assert_eq!(g.ui_nits(reported), 120);
|
||||
g.hdr_ui_nits = 400;
|
||||
assert_eq!((g.ui_nits(None), g.ui_nits(reported)), (400, 400));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hdr_modes_keep_boolean_files_and_round_trip_auto() {
|
||||
assert_eq!(Graphics::parse("").hdr, HdrMode::Off);
|
||||
@@ -1430,9 +1493,8 @@ mod tests {
|
||||
hdr_paper_white: 240,
|
||||
hdr_peak: 1400,
|
||||
hdr_black_level: 12,
|
||||
hdr_ui_brightness: 60,
|
||||
hdr_ui_nits: 160,
|
||||
hdr_lighting: false,
|
||||
hdr_key: "key.keyboard.h".into(),
|
||||
hdr_failed_start: Some(
|
||||
"Vulkan 10de:2684 NVIDIA GeForce RTX 4090; NVIDIA; 581.57".into(),
|
||||
),
|
||||
@@ -1574,6 +1636,10 @@ mod tests {
|
||||
Graphics::parse("shaderPack:Pack.zip\n"),
|
||||
Graphics::default()
|
||||
);
|
||||
// The HDR page's old shortcut key loads as nothing, and the next save drops it.
|
||||
let old = Graphics::parse("hdr:true\nhdrKey:key.keyboard.h\nhdrPeak:1000\n");
|
||||
assert_eq!((old.hdr, old.hdr_peak), (HdrMode::On, 1000));
|
||||
assert!(!old.serialize().contains("hdrKey"));
|
||||
assert_eq!(
|
||||
Graphics::parse(
|
||||
"workers:abc\nsky:maybe\ncullLeaves:true\nentityCulling:maybe\nleafCulling:maybe\n"
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::{
|
||||
lang,
|
||||
options_ui::{Event, Page as OptionsPage},
|
||||
settings::{Opt, Settings},
|
||||
settings_shell::{self as shell, Binding, Group, Output, Row, Screen, Sheet, Value},
|
||||
settings_shell::{self as shell, Group, Output, Row, Screen, Sheet, Value},
|
||||
text::Text,
|
||||
};
|
||||
|
||||
@@ -106,8 +106,6 @@ pub enum H {
|
||||
FrameGeneration,
|
||||
Hdr,
|
||||
HdrBlackLevel,
|
||||
/// Binds `Graphics::hdr_key`.
|
||||
HdrKey,
|
||||
/// Starts HDR calibration (`crate::hdr_calibration`).
|
||||
HdrCalibrate,
|
||||
HdrPeak,
|
||||
@@ -614,7 +612,7 @@ pub fn rows() -> Vec<(Page, Vec<(&'static str, Vec<Setting>)>)> {
|
||||
h(
|
||||
H::HdrUiBrightness,
|
||||
None,
|
||||
"How bright the HUD and menus are, against paper white.",
|
||||
"How bright the HUD and menus are. Auto: at paper white.",
|
||||
),
|
||||
h(
|
||||
H::HdrLighting,
|
||||
@@ -623,14 +621,6 @@ pub fn rows() -> Vec<(Page, Vec<(&'static str, Vec<Setting>)>)> {
|
||||
),
|
||||
],
|
||||
),
|
||||
(
|
||||
"Shortcut",
|
||||
vec![h(
|
||||
H::HdrKey,
|
||||
None,
|
||||
"A key that opens this screen from the game. Not bound at first.",
|
||||
)],
|
||||
),
|
||||
],
|
||||
),
|
||||
];
|
||||
@@ -819,14 +809,14 @@ impl H {
|
||||
H::ResolutionScale => Some((g.resolution_scale as f32 - 50.0) / 150.0),
|
||||
H::UpscalingSharpness => Some(g.upscaling_sharpness as f32 / 100.0),
|
||||
// Auto, then 10..480 by 10.
|
||||
H::HdrPaperWhite => Some(g.hdr_paper_white as f32 / 480.0),
|
||||
H::HdrPaperWhite => Some(crate::graphics::nits_position(g.hdr_paper_white)),
|
||||
H::HdrUiBrightness => Some(crate::graphics::nits_position(g.hdr_ui_nits)),
|
||||
// Auto, then the peak's scale.
|
||||
H::HdrPeak => Some(match g.hdr_peak {
|
||||
0 => 0.0,
|
||||
n => (1.0 + crate::graphics::peak_step_of(n as f32)) / PEAK_POSITIONS as f32,
|
||||
}),
|
||||
H::HdrBlackLevel => Some(g.hdr_black_level as f32 / 100.0),
|
||||
H::HdrUiBrightness => Some((g.hdr_ui_brightness as f32 - 25.0) / 75.0),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -838,13 +828,26 @@ impl H {
|
||||
H::Workers => Some(max_workers()),
|
||||
H::ResolutionScale => Some(30),
|
||||
H::UpscalingSharpness => Some(20),
|
||||
H::HdrPaperWhite => Some(48),
|
||||
H::HdrPaperWhite | H::HdrUiBrightness => Some(crate::graphics::NITS_STEPS),
|
||||
H::HdrPeak => Some(PEAK_POSITIONS),
|
||||
H::HdrBlackLevel => Some(100),
|
||||
H::HdrUiBrightness => Some(15),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
/// "Paper White: Auto (203)" or "Paper White: 160": a setting in nits, 0 for Auto, which
|
||||
/// shows the nits Auto gives.
|
||||
fn nits_label(self, s: &Settings, out: &EffectiveOutput) -> Text {
|
||||
let (g, r) = (&s.horizon, out.reported);
|
||||
let (caption, set, auto) = match self {
|
||||
H::HdrPaperWhite => ("Paper White", g.hdr_paper_white, g.paper_white_nits(r)),
|
||||
H::HdrPeak => ("Peak Brightness", g.hdr_peak, g.peak_nits(r)),
|
||||
_ => ("UI Brightness", g.hdr_ui_nits, g.ui_nits(r)),
|
||||
};
|
||||
match set {
|
||||
0 => labelled(caption, lang::tr("Auto (%s)", &[&auto])),
|
||||
n => labelled(caption, n),
|
||||
}
|
||||
}
|
||||
fn label(self, s: &Settings, out: &EffectiveOutput) -> Text {
|
||||
let g = &s.horizon;
|
||||
match self {
|
||||
@@ -945,26 +948,9 @@ impl H {
|
||||
Setup::Automatic => "Calibrate Anyway...",
|
||||
Setup::Changed => "Use Automatic Setup",
|
||||
})),
|
||||
H::HdrPaperWhite => match g.hdr_paper_white {
|
||||
0 => labelled(
|
||||
"Paper White",
|
||||
lang::tr("Auto (%s)", &[&g.paper_white_nits(out.reported)]),
|
||||
),
|
||||
n => labelled("Paper White", n.to_string()),
|
||||
},
|
||||
H::HdrPeak => match g.hdr_peak {
|
||||
0 => labelled(
|
||||
"Peak Brightness",
|
||||
lang::tr("Auto (%s)", &[&g.peak_nits(out.reported)]),
|
||||
),
|
||||
n => labelled("Peak Brightness", n.to_string()),
|
||||
},
|
||||
H::HdrPaperWhite | H::HdrPeak | H::HdrUiBrightness => self.nits_label(s, out),
|
||||
H::HdrBlackLevel => labelled("Black Level", format!("{:.2}", g.black_level_nits())),
|
||||
H::HdrUiBrightness => labelled_percent("UI Brightness", g.hdr_ui_brightness),
|
||||
H::HdrLighting => labelled("HDR Lighting", on_off(g.hdr_lighting)),
|
||||
H::HdrKey => {
|
||||
Text::translate("Shortcut: %s", &[crate::keybinds::display_name(&g.hdr_key)])
|
||||
}
|
||||
H::BatteryMode => labelled("Battery Mode", on_off(g.battery)),
|
||||
H::ShadowCache => labelled("Shadow Cache", on_off(g.shadow_cache)),
|
||||
// A press across the row, as Calibrate...: the list it opens shows the pick.
|
||||
@@ -1005,7 +991,8 @@ impl H {
|
||||
H::Workers => g.workers = (v * max_workers() as f32).round() as u32,
|
||||
H::ResolutionScale => g.resolution_scale = (50.0 + (v * 30.0).round() * 5.0) as u32,
|
||||
H::UpscalingSharpness => g.upscaling_sharpness = (v * 20.0).round() as u32 * 5,
|
||||
H::HdrPaperWhite => g.hdr_paper_white = (v * 48.0).round() as u32 * 10,
|
||||
H::HdrPaperWhite => g.hdr_paper_white = crate::graphics::nits_at(v),
|
||||
H::HdrUiBrightness => g.hdr_ui_nits = crate::graphics::nits_at(v),
|
||||
H::HdrPeak => {
|
||||
g.hdr_peak = match (v * PEAK_POSITIONS as f32).round() as u32 {
|
||||
0 => 0,
|
||||
@@ -1013,7 +1000,6 @@ impl H {
|
||||
}
|
||||
}
|
||||
H::HdrBlackLevel => g.hdr_black_level = (v * 100.0).round() as u32,
|
||||
H::HdrUiBrightness => g.hdr_ui_brightness = (25.0 + (v * 15.0).round() * 5.0) as u32,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -1189,10 +1175,7 @@ impl Item {
|
||||
fn steps(self, s: &Settings, out: &EffectiveOutput) -> bool {
|
||||
self.switch(s, out).is_none()
|
||||
&& self.slider(s).is_none()
|
||||
&& !matches!(
|
||||
self,
|
||||
Item::Horizon(H::HdrKey | H::HdrCalibrate | H::ShaderPacks)
|
||||
)
|
||||
&& !matches!(self, Item::Horizon(H::HdrCalibrate | H::ShaderPacks))
|
||||
}
|
||||
/// On/off settings and their value.
|
||||
pub fn switch(self, s: &Settings, out: &EffectiveOutput) -> Option<bool> {
|
||||
@@ -1347,12 +1330,6 @@ fn shown(item: Item, s: &Settings) -> bool {
|
||||
}
|
||||
/// A control's label as its name and its value ("Render Distance" and "12 chunks").
|
||||
fn parts(item: Item, s: &Settings, out: &EffectiveOutput) -> (String, Option<String>) {
|
||||
// The shortcut's label is one translated "Shortcut: %s"; the row shows its key apart, as
|
||||
// KeyBindsScreen does ("> key <" while it waits, `settings_shell::Value::Binding`).
|
||||
if item == Item::Horizon(H::HdrKey) {
|
||||
let key = crate::keybinds::display_name(&s.horizon.hdr_key).plain();
|
||||
return (lang::get("Shortcut"), Some(key));
|
||||
}
|
||||
shell::name_and_value(&item.label(s, out).plain())
|
||||
}
|
||||
|
||||
@@ -1361,13 +1338,9 @@ fn parts(item: Item, s: &Settings, out: &EffectiveOutput) -> (String, Option<Str
|
||||
fn row(setting: Setting, s: &Settings, out: &EffectiveOutput) -> Row<Item> {
|
||||
let item = setting.item;
|
||||
let (name, value) = parts(item, s, out);
|
||||
let value = match (item, item.switch(s, out), item.slider(s)) {
|
||||
(Item::Horizon(H::HdrKey), ..) => Value::Binding(Binding::key(
|
||||
crate::graphics::HDR_KEY,
|
||||
value.unwrap_or_default(),
|
||||
)),
|
||||
(_, Some(on), _) => Value::Switch(on),
|
||||
(_, None, Some(position)) => Value::Slider {
|
||||
let value = match (item.switch(s, out), item.slider(s)) {
|
||||
(Some(on), _) => Value::Switch(on),
|
||||
(None, Some(position)) => Value::Slider {
|
||||
position,
|
||||
steps: item.slider_steps(),
|
||||
text: value.unwrap_or_default(),
|
||||
@@ -1583,7 +1556,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
graphics_style as style,
|
||||
settings_shell::{Capture, Columns, Hosted, Shell, Target},
|
||||
settings_shell::{Columns, Hosted, Shell, Target},
|
||||
};
|
||||
use winit::keyboard::KeyCode as K;
|
||||
|
||||
@@ -2049,10 +2022,6 @@ mod tests {
|
||||
precheck.why.as_deref(),
|
||||
Some("Only applies to asynchronous entity culling.")
|
||||
);
|
||||
let key = find(&s, Item::Horizon(H::HdrKey));
|
||||
assert_eq!(key.name, "Shortcut");
|
||||
let waits = Capture::Key(crate::graphics::HDR_KEY);
|
||||
assert!(matches!(key.value, Value::Binding(ref b) if b.capture == waits));
|
||||
let calibrate = find(&s, Item::Horizon(H::HdrCalibrate));
|
||||
assert_eq!(calibrate.value, Value::Press);
|
||||
}
|
||||
@@ -2737,7 +2706,7 @@ mod tests {
|
||||
H::HdrPaperWhite => s.horizon.hdr_paper_white,
|
||||
H::HdrPeak => s.horizon.hdr_peak,
|
||||
H::HdrBlackLevel => s.horizon.hdr_black_level,
|
||||
H::HdrUiBrightness => s.horizon.hdr_ui_brightness,
|
||||
H::HdrUiBrightness => s.horizon.hdr_ui_nits,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let fresh = || {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//! reports.
|
||||
use super::tests::{CHANGED, CLICK, DRAGGED, FB, NONE, SIZE, Ui, offering, press, row, ui};
|
||||
use super::*;
|
||||
use crate::settings_shell::{Capture, Columns, Hosted};
|
||||
use crate::settings_shell::{Columns, Hosted};
|
||||
use winit::keyboard::KeyCode as K;
|
||||
|
||||
#[test]
|
||||
@@ -64,17 +64,12 @@ fn hdr_auto_can_be_selected_before_querying_and_brightness_waits_for_output() {
|
||||
let peak = row(&mut ui, &s, Item::Horizon(H::HdrPeak));
|
||||
assert_eq!(press(&mut ui, &mut s, (tx + 2.0, peak[1] + 4.0)), [DRAGGED]);
|
||||
ui.release();
|
||||
// Calibrate starts the calibration; the shortcut row waits for a key.
|
||||
// Calibrate starts the calibration.
|
||||
let calibrate = row(&mut ui, &s, Item::Horizon(H::HdrCalibrate));
|
||||
assert_eq!(
|
||||
press(&mut ui, &mut s, at(calibrate)),
|
||||
[CLICK, Output::Push(OptionsPage::HdrCalibration)]
|
||||
);
|
||||
let key = row(&mut ui, &s, Item::Horizon(H::HdrKey));
|
||||
assert_eq!(
|
||||
press(&mut ui, &mut s, at(key)),
|
||||
[CLICK, Output::Bind(Capture::Key(crate::graphics::HDR_KEY))]
|
||||
);
|
||||
assert!(ui.changed());
|
||||
}
|
||||
|
||||
@@ -135,6 +130,45 @@ fn hdr_setup_follows_what_the_system_reported() {
|
||||
assert_eq!(setup_of(&g, false), Setup::Unknown);
|
||||
}
|
||||
|
||||
/// UI Brightness reads as Paper White does, in nits apart from it: Auto shows the paper white
|
||||
/// in use, and a value set by hand its own nits, whatever Paper White is. Its slider has Paper
|
||||
/// White's steps: Auto, then 10 to 480 nits by 10.
|
||||
#[test]
|
||||
fn ui_brightness_reads_in_nits_on_paper_whites_steps() {
|
||||
let mut s = Settings::default();
|
||||
s.horizon.hdr = HdrMode::On;
|
||||
let reporting = offering(true, Some(true));
|
||||
let label = |s: &Settings, out| Item::Horizon(H::HdrUiBrightness).label(s, out).plain();
|
||||
assert_eq!(label(&s, &reporting), "UI Brightness: Auto (400)");
|
||||
assert_eq!(label(&s, &NONE), "UI Brightness: Auto (203)");
|
||||
s.horizon.hdr_paper_white = 250;
|
||||
assert_eq!(label(&s, &reporting), "UI Brightness: Auto (250)");
|
||||
s.horizon.hdr_ui_nits = 160;
|
||||
for paper_white in [0, 80, 250] {
|
||||
s.horizon.hdr_paper_white = paper_white;
|
||||
assert_eq!(label(&s, &reporting), "UI Brightness: 160");
|
||||
}
|
||||
let item = Item::Horizon(H::HdrUiBrightness);
|
||||
assert_eq!(
|
||||
H::HdrUiBrightness.slider_steps(),
|
||||
H::HdrPaperWhite.slider_steps()
|
||||
);
|
||||
H::HdrUiBrightness.set_slider(&mut s, 0.0);
|
||||
let mut reached = vec![s.horizon.hdr_ui_nits];
|
||||
for _ in 0..H::HdrUiBrightness.slider_steps().unwrap() {
|
||||
item.step_slider(&mut s, true, 200.0, &reporting);
|
||||
reached.push(s.horizon.hdr_ui_nits);
|
||||
}
|
||||
let paper: Vec<u32> = std::iter::once(0).chain((10..=480).step_by(10)).collect();
|
||||
assert_eq!(reached, paper);
|
||||
// Each value sits where Paper White's same value does.
|
||||
for nits in paper {
|
||||
s.horizon.hdr_ui_nits = nits;
|
||||
s.horizon.hdr_paper_white = nits;
|
||||
assert_eq!(item.slider(&s), Item::Horizon(H::HdrPaperWhite).slider(&s));
|
||||
}
|
||||
}
|
||||
|
||||
/// While HDR output is held back on this window's driver, the HDR row says so and keeps
|
||||
/// the mode; any change of the mode drops the hold, and HDR is asked for again.
|
||||
#[test]
|
||||
|
||||
@@ -206,8 +206,9 @@ fn display(light: vec3<f32>) -> vec4<f32> {
|
||||
let shows = params.world > 0.5 && params.peak > 1.0
|
||||
&& (hand || (!covered && shows_world(f.rgb, w.rgb)));
|
||||
var light = lit(f.rgb, w.a, shows, true).light;
|
||||
// The HUD and menus at their own brightness, by how much they cover.
|
||||
light *= mix(1.0, params.ui, ui);
|
||||
// The HUD and menus at their own brightness, by how much they cover, no brighter than the
|
||||
// peak (as `fs_hdr_layered`): UI Brightness can pass paper white.
|
||||
light = min(light * mix(1.0, params.ui, ui), vec3(params.peak));
|
||||
return display(light);
|
||||
}
|
||||
|
||||
@@ -275,8 +276,8 @@ fn backdrop(w: vec3<f32>) -> vec3<f32> {
|
||||
|
||||
// The HUD over the world in gamma, the space the HUD blends in: its own part, what its backdrop
|
||||
// B doesn't explain (H = P - (1 - c) B, exact for the layering blends), at UI Brightness, over
|
||||
// (1 - c) of the world, light above white included. Where the world is at or below white, at
|
||||
// 100%, that is the HUD's picture as drawn.
|
||||
// (1 - c) of the world, light above white included. Where the world is at or below white, with
|
||||
// UI Brightness at paper white, that is the HUD's picture as drawn.
|
||||
fn layered(at: vec2<i32>) -> vec3<f32> {
|
||||
let w = max(textureLoad(frame, at, 0).rgb, vec3(0.0));
|
||||
let p = textureLoad(hud, at, 0).rgb;
|
||||
|
||||
@@ -12,6 +12,7 @@ use std::{
|
||||
};
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
mod animate;
|
||||
pub mod cit_glint;
|
||||
mod pack_text;
|
||||
pub mod pictures;
|
||||
@@ -2876,59 +2877,6 @@ impl HudRenderer {
|
||||
pack_text::PackText::new(device, self.format, &self.atlas_view, shader, self.coverage)
|
||||
});
|
||||
}
|
||||
pub fn animate_sprites(
|
||||
&mut self,
|
||||
uploads: &mut crate::gfx::upload::Uploads,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
tick: u64,
|
||||
) {
|
||||
let Some(texture) = &self.atlas_texture else {
|
||||
return;
|
||||
};
|
||||
for (rect, animation, previous) in &mut self.sprite_animations {
|
||||
// `SpriteContents.AnimationState`: the frame from the mcmeta's
|
||||
// list, blended into the next one by the sub-frame's thousandths
|
||||
// when the sprite interpolates.
|
||||
let blend = animation.blend(tick);
|
||||
let state = (blend.frame, blend.next, blend.millis);
|
||||
if state == *previous {
|
||||
continue;
|
||||
}
|
||||
let (w, h) = rect.texels((texture.width(), texture.height()));
|
||||
let pixels = if blend.millis == 0 {
|
||||
animation.resized_pixels(blend.frame, w, h)
|
||||
} else {
|
||||
let current = animation.resized_pixels(blend.frame, w, h);
|
||||
let next = animation.resized_pixels(blend.next, w, h);
|
||||
let millis = blend.millis;
|
||||
current
|
||||
.iter()
|
||||
.zip(next)
|
||||
.map(|(&a, b)| {
|
||||
((u32::from(a) * (1000 - millis) + u32::from(b) * millis + 500) / 1000)
|
||||
as u8
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
uploads.texture(
|
||||
encoder,
|
||||
wgpu::TexelCopyTextureInfo {
|
||||
texture,
|
||||
mip_level: 0,
|
||||
origin: wgpu::Origin3d {
|
||||
x: (rect.u0 * texture.width() as f32).round() as u32,
|
||||
y: (rect.v0 * texture.height() as f32).round() as u32,
|
||||
z: 0,
|
||||
},
|
||||
aspect: wgpu::TextureAspect::All,
|
||||
},
|
||||
w,
|
||||
h,
|
||||
&pixels,
|
||||
);
|
||||
*previous = state;
|
||||
}
|
||||
}
|
||||
/// Stage `patches` into the shared atlas texture.
|
||||
pub fn upload_patches(
|
||||
&self,
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
//! The GUI atlas's animated sprites, frame by frame (vanilla's or a Polytone `mode`'s).
|
||||
|
||||
impl super::HudRenderer {
|
||||
/// Shows each animated sprite's frame: its mcmeta's, or what its Polytone `mode` picks.
|
||||
pub(crate) fn animate(
|
||||
&mut self,
|
||||
uploads: &mut crate::gfx::upload::Uploads,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
tick: u64,
|
||||
animator: &crate::gfx::animate::SpriteAnimator,
|
||||
) {
|
||||
let inputs = animator.mode_inputs();
|
||||
let inputs = Some(&inputs);
|
||||
let Some(texture) = &self.atlas_texture else {
|
||||
return;
|
||||
};
|
||||
for (rect, animation, previous) in &mut self.sprite_animations {
|
||||
// `SpriteContents.AnimationState`: the frame from the mcmeta's
|
||||
// list, blended into the next one by the sub-frame's thousandths
|
||||
// when the sprite interpolates; or what a Polytone `mode` picks.
|
||||
let blend = animation.blend_with(tick, inputs);
|
||||
let state = (blend.frame, blend.next, blend.millis);
|
||||
if state == *previous {
|
||||
continue;
|
||||
}
|
||||
let (w, h) = rect.texels((texture.width(), texture.height()));
|
||||
let pixels = if blend.millis == 0 {
|
||||
animation.resized_pixels(blend.frame, w, h)
|
||||
} else {
|
||||
let current = animation.resized_pixels(blend.frame, w, h);
|
||||
let next = animation.resized_pixels(blend.next, w, h);
|
||||
let millis = blend.millis;
|
||||
current
|
||||
.iter()
|
||||
.zip(next)
|
||||
.map(|(&a, b)| {
|
||||
((u32::from(a) * (1000 - millis) + u32::from(b) * millis + 500) / 1000)
|
||||
as u8
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
uploads.texture(
|
||||
encoder,
|
||||
wgpu::TexelCopyTextureInfo {
|
||||
texture,
|
||||
mip_level: 0,
|
||||
origin: wgpu::Origin3d {
|
||||
x: (rect.u0 * texture.width() as f32).round() as u32,
|
||||
y: (rect.v0 * texture.height() as f32).round() as u32,
|
||||
z: 0,
|
||||
},
|
||||
aspect: wgpu::TextureAspect::All,
|
||||
},
|
||||
w,
|
||||
h,
|
||||
&pixels,
|
||||
);
|
||||
*previous = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 90 B |
|
After Width: | Height: | Size: 103 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 172 B |
|
After Width: | Height: | Size: 133 B |
|
After Width: | Height: | Size: 142 B |
|
After Width: | Height: | Size: 103 B |
@@ -27,4 +27,29 @@ pub(crate) const SPRITES: &[(&str, &[u8])] = &[
|
||||
"search_background_v2",
|
||||
include_bytes!("jei_recipes/search_background_v2.png"),
|
||||
),
|
||||
("slot", include_bytes!("jei_recipes/slot.png")),
|
||||
(
|
||||
"icons/list_badge",
|
||||
include_bytes!("jei_recipes/icons/list_badge.png"),
|
||||
),
|
||||
(
|
||||
"interactive_ingredient_tooltip_background",
|
||||
include_bytes!("jei_recipes/interactive_ingredient_tooltip_background.png"),
|
||||
),
|
||||
(
|
||||
"recipe_preview_background_v2",
|
||||
include_bytes!("jei_recipes/recipe_preview_background_v2.png"),
|
||||
),
|
||||
(
|
||||
"ingredient_list_slot_background_v2",
|
||||
include_bytes!("jei_recipes/ingredient_list_slot_background_v2.png"),
|
||||
),
|
||||
(
|
||||
"scrollbar_background_v2",
|
||||
include_bytes!("jei_recipes/scrollbar_background_v2.png"),
|
||||
),
|
||||
(
|
||||
"scrollbar_marker_v2",
|
||||
include_bytes!("jei_recipes/scrollbar_marker_v2.png"),
|
||||
),
|
||||
];
|
||||
@@ -68,6 +68,7 @@ pub mod jigsaw_block;
|
||||
pub mod keypad;
|
||||
pub mod terrain_model;
|
||||
pub use horizon_polytone::colors as polytone_colors;
|
||||
pub use horizon_polytone::creative_tabs as polytone_creative_tabs;
|
||||
pub use horizon_world::json_folder;
|
||||
pub mod level_loading;
|
||||
pub mod light;
|
||||
|
||||
@@ -761,6 +761,49 @@ pub struct MeshTables {
|
||||
colormaps: Vec<Arc<crate::environment::Colormap>>,
|
||||
water_colormap: Option<u16>,
|
||||
}
|
||||
/// Vanilla's four biome colour functions (`BiomeColors`) with what the packs replace them by:
|
||||
/// `biome_colors` (a colormap or a flat colour), else the colormap a block modifier gives
|
||||
/// `grass_block`, `oak_leaves` or `leaf_litter`, or a fluid modifier gives water, which Polytone
|
||||
/// spreads to every block of that function. Each with the tints that read it.
|
||||
fn biome_functions(
|
||||
pack_root: &std::path::Path,
|
||||
modifiers: &[(bool, horizon_polytone::Targets, String)],
|
||||
) -> Vec<(&'static [Tint], crate::environment::Colormap)> {
|
||||
use crate::environment::Colormap;
|
||||
use horizon_polytone::colors::BiomeColor;
|
||||
const FUNCTIONS: [(&str, &str, &[Tint]); 4] = [
|
||||
(
|
||||
"grass",
|
||||
"minecraft:grass_block",
|
||||
&[
|
||||
Tint::Grass,
|
||||
Tint::GrassBlock,
|
||||
Tint::TallGrassUpper,
|
||||
Tint::SugarCane,
|
||||
],
|
||||
),
|
||||
("foliage", "minecraft:oak_leaves", &[Tint::Foliage]),
|
||||
("dry_foliage", "minecraft:leaf_litter", &[Tint::DryFoliage]),
|
||||
("water", "minecraft:water", &[Tint::Water]),
|
||||
];
|
||||
let colors = horizon_polytone::colors::PackColors::read(pack_root);
|
||||
FUNCTIONS
|
||||
.into_iter()
|
||||
.filter_map(|(function, block, tints)| {
|
||||
let colormap = match colors.biome_color(function) {
|
||||
Some(BiomeColor::Flat(rgb)) => Some(Colormap::flat(rgb)),
|
||||
Some(BiomeColor::Colormap(id)) => Colormap::load(pack_root, &id),
|
||||
None => modifiers
|
||||
.iter()
|
||||
.find(|(fluid, targets, _)| {
|
||||
*fluid == (function == "water") && targets.matches(block, |_| false)
|
||||
})
|
||||
.and_then(|(_, _, id)| Colormap::load(pack_root, id)),
|
||||
}?;
|
||||
Some((tints, colormap))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
fn stem_color(age: u8) -> u32 {
|
||||
let a = u32::from(age);
|
||||
(a * 32) << 16 | (255 - a * 8) << 8 | (a * 4)
|
||||
@@ -945,7 +988,8 @@ impl MeshTables {
|
||||
}
|
||||
/// These tables with the colormaps of the Polytone block and fluid modifiers of the packs
|
||||
/// merged at `pack_root` (wiki "Colormaps"): a tinted block they target takes its colour
|
||||
/// from the colormap, and its own tint where the colormap's pixel is transparent.
|
||||
/// from the colormap, and its own tint where the colormap's pixel is transparent. Vanilla's
|
||||
/// four biome colour functions take the packs' `biome_colors` first (wiki "Custom Colors").
|
||||
#[must_use]
|
||||
pub fn with_polytone_colormaps(
|
||||
mut self,
|
||||
@@ -953,7 +997,8 @@ impl MeshTables {
|
||||
registry: &horizon_world::registry::BlockRegistry,
|
||||
) -> Self {
|
||||
let modifiers = crate::environment::polytone_colormap_modifiers(pack_root);
|
||||
if modifiers.is_empty() {
|
||||
let biome_functions = biome_functions(pack_root, &modifiers);
|
||||
if modifiers.is_empty() && biome_functions.is_empty() {
|
||||
return self;
|
||||
}
|
||||
let mut loaded: std::collections::HashMap<String, Option<u16>> = Default::default();
|
||||
@@ -964,7 +1009,24 @@ impl MeshTables {
|
||||
Some((colormaps.len() - 1) as u16)
|
||||
})
|
||||
};
|
||||
for (tints, colormap) in biome_functions {
|
||||
self.colormaps.push(Arc::new(colormap));
|
||||
let i = Some((self.colormaps.len() - 1) as u16);
|
||||
if tints == [Tint::Water] {
|
||||
self.water_colormap = i;
|
||||
}
|
||||
for info in &mut self.info {
|
||||
let own = &info.tints[..usize::from(info.tint_count).min(2)];
|
||||
if own.iter().any(|t| tints.contains(t)) {
|
||||
info.colormap = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
let water_function = self.water_colormap;
|
||||
for (fluid, targets, id) in &modifiers {
|
||||
if *fluid && water_function.is_some() {
|
||||
continue;
|
||||
}
|
||||
if *fluid {
|
||||
if targets.matches("minecraft:water", |_| false) {
|
||||
self.water_colormap = index(id, &mut self.colormaps);
|
||||
@@ -1495,9 +1557,9 @@ struct Tints<'a> {
|
||||
/// by colormap and section-local block.
|
||||
colormaps: &'a [Arc<crate::environment::Colormap>],
|
||||
water_colormap: Option<u16>,
|
||||
sampled: std::collections::HashMap<(u16, [i32; 3]), Option<u32>>,
|
||||
sampled: crate::fast_hash::FxHashMap<(u16, [i32; 3]), Option<u32>>,
|
||||
/// Each colormap's own colour by block, before the blend averages them.
|
||||
cells: std::collections::HashMap<(u16, [i32; 3]), Option<u32>>,
|
||||
cells: crate::fast_hash::FxHashMap<(u16, [i32; 3]), Option<u32>>,
|
||||
}
|
||||
impl<'a> Tints<'a> {
|
||||
fn new(
|
||||
@@ -1518,8 +1580,8 @@ impl<'a> Tints<'a> {
|
||||
uniform: None,
|
||||
colormaps: &[],
|
||||
water_colormap: None,
|
||||
sampled: std::collections::HashMap::new(),
|
||||
cells: std::collections::HashMap::new(),
|
||||
sampled: Default::default(),
|
||||
cells: Default::default(),
|
||||
}
|
||||
}
|
||||
/// With the packs' colormaps of `tables`.
|
||||
@@ -1531,10 +1593,16 @@ impl<'a> Tints<'a> {
|
||||
/// Colormap `index`'s colour at block `(x, y, z)` (section-local), `None` where its pixel
|
||||
/// is transparent.
|
||||
fn colormap(&mut self, index: u16, x: i32, y: i32, z: i32) -> Option<u32> {
|
||||
let colormap = self.colormaps.get(usize::from(index))?.clone();
|
||||
// A colormap that ignores the height, over one biome: one colour per column.
|
||||
let y = if colormap.column && self.uniform_biome().is_some() {
|
||||
0
|
||||
} else {
|
||||
y
|
||||
};
|
||||
if let Some(&known) = self.sampled.get(&(index, [x, y, z])) {
|
||||
return known;
|
||||
}
|
||||
let colormap = self.colormaps.get(usize::from(index))?.clone();
|
||||
// ClientLevel.calculateBlockTint: the mean of the (2r+1)^2 colours around the block, each
|
||||
// channel summed and divided. A transparent pixel in the square leaves the block's own.
|
||||
let r = if colormap.biome_blend { self.radius } else { 0 };
|
||||
@@ -1573,7 +1641,11 @@ impl<'a> Tints<'a> {
|
||||
if let Some(&known) = self.cells.get(&(index, at)) {
|
||||
return known;
|
||||
}
|
||||
let id = Self::biome_id(&self.zoom, self.region, self.plains, self.origin, at);
|
||||
// One biome over the section and its blend margin: no zoom per block.
|
||||
let id = match self.uniform_biome() {
|
||||
Some(biome) => biome,
|
||||
None => Self::biome_id(&self.zoom, self.region, self.plains, self.origin, at),
|
||||
};
|
||||
let [cx, cz, base_y] = self.origin;
|
||||
let block = [cx * 16 + at[0], base_y + at[1], cz * 16 + at[2]];
|
||||
let mut host = crate::environment::BlockHost::new(block, self.biomes.get(id));
|
||||
|
||||
@@ -251,3 +251,117 @@ fn a_biome_colormap_blends_over_a_biome_edge_as_the_vanilla_water_tint_does() {
|
||||
}
|
||||
assert!(edge_differs, "the square must cross the edge somewhere");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn biome_colors_and_a_grass_block_colormap_replace_their_whole_biome_function() {
|
||||
let biomes = Biomes::from_jsons(&[(
|
||||
"minecraft:plains",
|
||||
serde_json::json!({"effects": {"water_color": 0x3F76E4}}),
|
||||
)]);
|
||||
// biome_colors gives water a flat green; a block modifier colours oak leaves with a map,
|
||||
// which Polytone spreads to the whole foliage function.
|
||||
let root = pack(&[
|
||||
(
|
||||
"assets/mypack/polytone/colors.json",
|
||||
br#"{"biome_colors": {"water": "0x00ff00"}}"#.to_vec(),
|
||||
),
|
||||
(
|
||||
"assets/mypack/polytone/colormaps/leaves.png",
|
||||
png_row(&[[0, 0, 255, 255]]),
|
||||
),
|
||||
(
|
||||
"assets/mypack/polytone/block_modifiers/oak.json",
|
||||
br#"{"targets": ["minecraft:oak_leaves"], "colormap": "mypack:leaves"}"#.to_vec(),
|
||||
),
|
||||
]);
|
||||
let modifiers = crate::environment::polytone_colormap_modifiers(&root);
|
||||
let functions = biome_functions(&root, &modifiers);
|
||||
let tints: Vec<_> = functions.iter().map(|(t, _)| *t).collect();
|
||||
assert_eq!(tints.len(), 2);
|
||||
assert!(tints[0] == [Tint::Foliage] && tints[1] == [Tint::Water]);
|
||||
let colormaps: Vec<_> = functions.into_iter().map(|(_, c)| Arc::new(c)).collect();
|
||||
let chunks: Vec<Vec<Chunk>> = (0..3)
|
||||
.map(|rz| (0..3).map(|rx| filled(rx - 1, rz - 1, 0)).collect())
|
||||
.collect();
|
||||
let region: [[Option<&Chunk>; 3]; 3] =
|
||||
std::array::from_fn(|rz| std::array::from_fn(|rx| Some(&chunks[rz][rx])));
|
||||
let mut tints = Tints::new(®ion, &biomes, BiomeZoom::new(0), 0, [0, 0, 64]);
|
||||
tints.colormaps = &colormaps;
|
||||
tints.water_colormap = Some(1);
|
||||
assert_eq!(tints.water(3, 4, 5), 0x00_FF00);
|
||||
std::fs::remove_dir_all(root).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_a_colormap_that_ignores_the_height_is_shared_up_a_column() {
|
||||
let root = pack(&[
|
||||
(
|
||||
"assets/mypack/polytone/colormaps/flat.png",
|
||||
png_row(&[[1, 2, 3, 255]]),
|
||||
),
|
||||
(
|
||||
"assets/mypack/polytone/colormaps/flat.json",
|
||||
br#"{"x_axis": "biome_id", "y_axis": "r.noise(o.x/60, o.z/60)"}"#.to_vec(),
|
||||
),
|
||||
(
|
||||
"assets/mypack/polytone/colormaps/tall.png",
|
||||
png_row(&[[1, 2, 3, 255]]),
|
||||
),
|
||||
(
|
||||
"assets/mypack/polytone/colormaps/tall.json",
|
||||
br#"{"y_axis": "y_level"}"#.to_vec(),
|
||||
),
|
||||
]);
|
||||
let load = |id| crate::environment::Colormap::load(&root, id).unwrap();
|
||||
assert!(load("mypack:flat").column);
|
||||
assert!(!load("mypack:tall").column);
|
||||
std::fs::remove_dir_all(root).unwrap();
|
||||
}
|
||||
|
||||
/// Times a section's colormap tints with the freepack's kind of grass colormap (a biome id
|
||||
/// column and a noise row) over the default Biome Blend: `cargo test --release ... -- --ignored
|
||||
/// --nocapture colormap_tint_cost`.
|
||||
#[test]
|
||||
#[ignore = "timing, not a check"]
|
||||
fn colormap_tint_cost() {
|
||||
const RADIUS: i32 = 2;
|
||||
const LAYERS: i32 = 16;
|
||||
let biomes = Biomes::from_jsons(&[(
|
||||
"minecraft:plains",
|
||||
serde_json::json!({"effects": {"water_color": 0x3F76E4}}),
|
||||
)]);
|
||||
let pixels: Vec<[u8; 4]> = (0..16).map(|i| [i * 16, 200, 64, 255]).collect();
|
||||
let root = pack(&[
|
||||
("assets/mypack/polytone/colormaps/grass.png", png_row(&pixels)),
|
||||
(
|
||||
"assets/mypack/polytone/colormaps/grass.json",
|
||||
br#"{"x_axis": "biome_id", "y_axis": "0.5+(r.noise(o.x/60,5+o.z/60)*0.55)", "biome_id_mapper": {"minecraft:plains": 1, "texture_size": 16}}"#
|
||||
.to_vec(),
|
||||
),
|
||||
]);
|
||||
let colormaps = vec![Arc::new(
|
||||
crate::environment::Colormap::load(&root, "mypack:grass").unwrap(),
|
||||
)];
|
||||
let chunks: Vec<Vec<Chunk>> = (0..3)
|
||||
.map(|rz| (0..3).map(|rx| filled(rx - 1, rz - 1, 0)).collect())
|
||||
.collect();
|
||||
let region: [[Option<&Chunk>; 3]; 3] =
|
||||
std::array::from_fn(|rz| std::array::from_fn(|rx| Some(&chunks[rz][rx])));
|
||||
let rounds = 50;
|
||||
let start = std::time::Instant::now();
|
||||
let mut check = 0u64;
|
||||
for _ in 0..rounds {
|
||||
let mut tints = Tints::new(®ion, &biomes, BiomeZoom::new(0), RADIUS, [0, 0, 64]);
|
||||
tints.colormaps = &colormaps;
|
||||
for y in 0..LAYERS {
|
||||
for z in 0..16 {
|
||||
for x in 0..16 {
|
||||
check += u64::from(tints.colormap(0, x, y, z).unwrap_or(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let per = start.elapsed() / rounds;
|
||||
println!("{LAYERS} layers of 256 blended colormap tints: {per:?} (checksum {check})");
|
||||
std::fs::remove_dir_all(root).unwrap();
|
||||
}
|
||||
@@ -1331,6 +1331,8 @@ pub enum Page {
|
||||
ModProject,
|
||||
/// A native mod's settings page: its index in `mods.installed`.
|
||||
NativeMod(usize),
|
||||
/// A page a crate registered (`horizon_hooks::pages`): its index in `OptionsUi::pages`.
|
||||
Added(usize),
|
||||
/// Horizon's shader packs, either kind (`shader_pack_list`).
|
||||
ShaderPacks,
|
||||
/// The picked pack's options: the shader screen (`shader_ui`) at the pack's main screen.
|
||||
@@ -1390,6 +1392,8 @@ enum Act {
|
||||
/// A native mod's key (mod, key) waits for a key; a button of its page.
|
||||
NativeKey(usize, usize),
|
||||
NativeButton(usize, usize),
|
||||
/// A registered page's row: (page, row).
|
||||
PageRow(usize, usize),
|
||||
OpenModFolder,
|
||||
/// Browse mods: the page of listing `.0` of `mod_browser`.
|
||||
ModProject(usize),
|
||||
@@ -1617,8 +1621,11 @@ pub struct OptionsUi {
|
||||
/// Key Binds: the mapping waiting for a key ([`NATIVE_KEY`]: a native
|
||||
/// mod's, `selected_native_key`).
|
||||
pub selected_key: Option<&'static str>,
|
||||
/// The native mod's key waiting: (mod, key) in `mods.installed`.
|
||||
/// The native mod's key waiting: (mod, key) in `mods.installed`, or a registered page's
|
||||
/// (page, row) ([`pages::PAGE_KEY`]).
|
||||
selected_native_key: Option<(usize, usize)>,
|
||||
/// The pages crates registered (`horizon_hooks::pages`).
|
||||
pages: &'static [&'static dyn horizon_hooks::pages::Page],
|
||||
/// Bindings: the action waiting for a pad button.
|
||||
pub selected_pad_action: Option<&'static str>,
|
||||
/// The glyphs menus show (`Glyphs::of`: the setting, else the pad's family, and a Nintendo
|
||||
@@ -1730,6 +1737,7 @@ impl Default for OptionsUi {
|
||||
scrollbar_drag_y: None,
|
||||
selected_key: None,
|
||||
selected_native_key: None,
|
||||
pages: horizon_hooks::pages::engine::all(),
|
||||
selected_pad_action: None,
|
||||
pad_glyphs: crate::pad_glyph::Glyphs::default(),
|
||||
pad_driving: false,
|
||||
@@ -2367,6 +2375,7 @@ impl OptionsUi {
|
||||
Page::ModBrowser => "horizon.mods.browse.title",
|
||||
Page::ModProject => "horizon.mods.browse.project",
|
||||
Page::NativeMod(_) => "Mod Settings",
|
||||
Page::Added(i) => pages::title(i),
|
||||
Page::ShaderPacks => "horizon.pages.shader_packs",
|
||||
Page::ShaderOptions => "horizon.pages.shader_options",
|
||||
Page::PackOptions => "horizon.pack.options.title",
|
||||
@@ -2583,43 +2592,6 @@ impl OptionsUi {
|
||||
}
|
||||
rows
|
||||
}
|
||||
/// A native mod's page: its name, its keys as Key Binds rows (the
|
||||
/// player's choice, else the default), then its buttons.
|
||||
fn native_rows(&self, s: &Settings, i: usize) -> Vec<Row> {
|
||||
let Some(m) = s.mods.installed.get(i) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let mut rows = vec![Row::Note(m.title.clone())];
|
||||
let Some(page) = &m.native else {
|
||||
return rows;
|
||||
};
|
||||
let chosen = s.mods.keys.get(&m.id);
|
||||
for (k, [name, label, default]) in page.keys.iter().enumerate() {
|
||||
let key = chosen.and_then(|c| c.get(name)).unwrap_or(default);
|
||||
let mut message = keybinds::display_name(key);
|
||||
if self.selected_native_key == Some((i, k)) {
|
||||
message = Text::literal("> ")
|
||||
.append(message.with_color(text::WHITE))
|
||||
.append(" <")
|
||||
.with_color(text::YELLOW);
|
||||
}
|
||||
let caption = button(0.0, 0.0, 150.0, Text::literal(label.clone()), Act::None);
|
||||
let change = button(0.0, 0.0, 150.0, message, Act::NativeKey(i, k));
|
||||
rows.push(Row::Buttons(inactive(caption), Some(change)));
|
||||
}
|
||||
for (b, label) in page.buttons.iter().enumerate() {
|
||||
let widget = button(
|
||||
0.0,
|
||||
0.0,
|
||||
310.0,
|
||||
Text::literal(label.clone()),
|
||||
Act::NativeButton(i, b),
|
||||
);
|
||||
rows.push(Row::Buttons(widget, None));
|
||||
}
|
||||
rows
|
||||
}
|
||||
|
||||
fn list_rows(&self, s: &Settings) -> Vec<Row> {
|
||||
match self.page() {
|
||||
Page::SplitSetup => Vec::new(),
|
||||
@@ -2684,47 +2656,7 @@ impl OptionsUi {
|
||||
flush(&mut rows, &mut section);
|
||||
rows
|
||||
}
|
||||
Page::Horizon => {
|
||||
// Two to a row, as vanilla's OptionsList.addSmall lays out
|
||||
// buttons; each opens one of Horizon's settings pages. Each page has
|
||||
// one way in: graphics and shader packs are Video Settings' (the graphics
|
||||
// screen), the controller is Controls', mods are the Options screen's.
|
||||
let open =
|
||||
|key: &str, page: Page| button(0.0, 0.0, 150.0, tr(key), Act::Push(page));
|
||||
vec![
|
||||
Row::Buttons(
|
||||
open("horizon.pages.open.extras", Page::Extras),
|
||||
Some(open("horizon.pages.open.pvp", Page::Pvp)),
|
||||
),
|
||||
Row::Buttons(
|
||||
open(
|
||||
"horizon.pages.open.split_setup",
|
||||
if self.split_guest {
|
||||
Page::SplitProfiles
|
||||
} else {
|
||||
Page::SplitSetup
|
||||
},
|
||||
),
|
||||
Some(open("horizon.pages.open.studio", Page::Studio)),
|
||||
),
|
||||
// No AI hides the AI Agent page and everything AI.
|
||||
Row::Buttons(
|
||||
self.extra_button(s, crate::extras::Item::DiscordPresence),
|
||||
Some(if s.extras.no_ai {
|
||||
self.extra_button(s, crate::extras::Item::NoAi)
|
||||
} else {
|
||||
open("horizon.pages.open.agent", Page::Agent)
|
||||
}),
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.chain(
|
||||
(!s.extras.no_ai).then(|| {
|
||||
Row::Buttons(self.extra_button(s, crate::extras::Item::NoAi), None)
|
||||
}),
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
Page::Horizon => self.horizon_rows(s),
|
||||
Page::Agent => {
|
||||
let mut rows = vec![Row::Buttons(
|
||||
self.extra_button(s, crate::extras::Item::AgentControl),
|
||||
@@ -3007,6 +2939,7 @@ impl OptionsUi {
|
||||
Page::ModBrowser => self.mod_browser_rows(),
|
||||
Page::ModProject => self.mod_project_rows(s),
|
||||
Page::NativeMod(i) => self.native_rows(s, i),
|
||||
Page::Added(i) => self.added_rows(i),
|
||||
_ => {
|
||||
let _ = s;
|
||||
Vec::new()
|
||||
@@ -4273,11 +4206,9 @@ impl OptionsUi {
|
||||
self.push(Page::NativeMod(i));
|
||||
events.push(Event::NativeSettings(i));
|
||||
}
|
||||
Act::NativeKey(i, k) => {
|
||||
self.selected_key = Some(NATIVE_KEY);
|
||||
self.selected_native_key = Some((i, k));
|
||||
}
|
||||
Act::NativeKey(i, k) => self.wait_native_key(i, k),
|
||||
Act::NativeButton(i, b) => events.push(Event::NativeButton(i, b)),
|
||||
Act::PageRow(p, r) => events.extend(self.page_act(p, r, self.shift)),
|
||||
Act::OpenModFolder => events.push(Event::OpenModFolder),
|
||||
Act::ModProject(i) => {
|
||||
if let Some(listing) = self.mod_browser.listings.get(i) {
|
||||
@@ -4781,19 +4712,10 @@ impl OptionsUi {
|
||||
let Some(name) = self.selected_key.take() else {
|
||||
return Vec::new();
|
||||
};
|
||||
if name == NATIVE_KEY {
|
||||
let (i, k) = self.selected_native_key.take().unwrap_or_default();
|
||||
let Some(m) = s.mods.installed.get(i) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let Some([key, ..]) = m.native.as_ref().and_then(|p| p.keys.get(k)) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let keys = s.mods.keys.entry(m.id.clone()).or_default();
|
||||
keys.insert(key.clone(), value);
|
||||
return vec![Event::Changed];
|
||||
if name == NATIVE_KEY || name == pages::PAGE_KEY {
|
||||
return self.bind_native_key(s, name, value);
|
||||
}
|
||||
if !s.extras.set_key(name, value.clone()) && !s.horizon.set_key(name, value.clone()) {
|
||||
if !s.extras.set_key(name, value.clone()) {
|
||||
s.keys.set(name, &value);
|
||||
}
|
||||
vec![Event::Changed]
|
||||
@@ -5173,11 +5095,9 @@ impl OptionsUi {
|
||||
self.push(Page::NativeMod(i));
|
||||
events.push(Event::NativeSettings(i));
|
||||
}
|
||||
Act::NativeKey(i, k) => {
|
||||
self.selected_key = Some(NATIVE_KEY);
|
||||
self.selected_native_key = Some((i, k));
|
||||
}
|
||||
Act::NativeKey(i, k) => self.wait_native_key(i, k),
|
||||
Act::NativeButton(i, b) => events.push(Event::NativeButton(i, b)),
|
||||
Act::PageRow(p, r) => events.extend(self.page_act(p, r, shift)),
|
||||
Act::OpenModFolder => events.push(Event::OpenModFolder),
|
||||
Act::ModProject(i) => {
|
||||
if let Some(listing) = self.mod_browser.listings.get(i) {
|
||||
@@ -7348,7 +7268,7 @@ mod tests {
|
||||
MouseButton::Back,
|
||||
MouseButton::Forward,
|
||||
] {
|
||||
for name in [SORT_KEY, crate::graphics::HDR_KEY, "key.jump"] {
|
||||
for name in [SORT_KEY, "key.jump"] {
|
||||
let mut ui = OptionsUi::default();
|
||||
let mut s = Settings::default();
|
||||
ui.selected_key = Some(name);
|
||||
@@ -7357,7 +7277,6 @@ mod tests {
|
||||
let value = keybinds::mouse_name(button);
|
||||
match name {
|
||||
SORT_KEY => assert_eq!(s.extras.sort_key, value),
|
||||
crate::graphics::HDR_KEY => assert_eq!(s.horizon.hdr_key, value),
|
||||
_ => assert_eq!(s.keys.get(name), value),
|
||||
}
|
||||
assert_eq!(Extras::parse(&s.extras.serialize()), s.extras);
|
||||
@@ -8439,3 +8358,5 @@ mod tests {
|
||||
#[cfg(test)]
|
||||
#[path = "options_ui_graphics_tests.rs"]
|
||||
mod graphics_tests;
|
||||
#[path = "options_ui_pages.rs"]
|
||||
mod pages;
|
||||
@@ -0,0 +1,327 @@
|
||||
//! The pages crates add to the options screens: a native mod's settings page (its keys and
|
||||
//! buttons), and the pages crates above the engine register (`horizon_hooks::pages`, docs/layers.md
|
||||
//! "Platform registries") with their entries on Horizon Settings. Kept out of options_ui.rs, which
|
||||
//! may not grow (tools/check_file_size.py).
|
||||
use super::*;
|
||||
use horizon_hooks::pages as added;
|
||||
|
||||
/// `selected_key` while a registered page's key waits (`selected_native_key`: page, row).
|
||||
pub(super) const PAGE_KEY: &str = "horizon.pageKey";
|
||||
|
||||
/// A registered page's title (a translation key).
|
||||
pub(super) fn title(page: usize) -> &'static str {
|
||||
added::engine::all().get(page).map_or("", |p| p.title())
|
||||
}
|
||||
|
||||
fn label_text(label: added::Label) -> Text {
|
||||
match label {
|
||||
added::Label::Key(key) => tr(key),
|
||||
added::Label::Value(value) => Text::literal(value),
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionsUi {
|
||||
/// Horizon Settings: its pages, then the pages crates registered for it.
|
||||
pub(super) fn horizon_rows(&self, s: &Settings) -> Vec<Row> {
|
||||
// Two to a row, as vanilla's OptionsList.addSmall lays out
|
||||
// buttons; each opens one of Horizon's settings pages. Each page has
|
||||
// one way in: graphics and shader packs are Video Settings' (the graphics
|
||||
// screen), the controller is Controls', mods are the Options screen's.
|
||||
let open = |key: &str, page: Page| button(0.0, 0.0, 150.0, tr(key), Act::Push(page));
|
||||
let mut rows: Vec<Row> = vec![
|
||||
Row::Buttons(
|
||||
open("horizon.pages.open.extras", Page::Extras),
|
||||
Some(open("horizon.pages.open.pvp", Page::Pvp)),
|
||||
),
|
||||
Row::Buttons(
|
||||
open(
|
||||
"horizon.pages.open.split_setup",
|
||||
if self.split_guest {
|
||||
Page::SplitProfiles
|
||||
} else {
|
||||
Page::SplitSetup
|
||||
},
|
||||
),
|
||||
Some(open("horizon.pages.open.studio", Page::Studio)),
|
||||
),
|
||||
// No AI hides the AI Agent page and everything AI.
|
||||
Row::Buttons(
|
||||
self.extra_button(s, crate::extras::Item::DiscordPresence),
|
||||
Some(if s.extras.no_ai {
|
||||
self.extra_button(s, crate::extras::Item::NoAi)
|
||||
} else {
|
||||
open("horizon.pages.open.agent", Page::Agent)
|
||||
}),
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.chain(
|
||||
(!s.extras.no_ai)
|
||||
.then(|| Row::Buttons(self.extra_button(s, crate::extras::Item::NoAi), None)),
|
||||
)
|
||||
.collect();
|
||||
self.added_entries(&mut rows);
|
||||
rows
|
||||
}
|
||||
|
||||
/// The entries of the pages registered for Horizon Settings, two to a row like the engine's.
|
||||
fn added_entries(&self, rows: &mut Vec<Row>) {
|
||||
let mut entries = self
|
||||
.pages
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, page)| page.place() == added::Place::HorizonSettings)
|
||||
.map(|(i, page)| button(0.0, 0.0, 150.0, tr(page.title()), Act::Push(Page::Added(i))));
|
||||
while let Some(first) = entries.next() {
|
||||
rows.push(Row::Buttons(first, entries.next()));
|
||||
}
|
||||
}
|
||||
|
||||
/// A registered page's rows, asked of it each time the page is drawn.
|
||||
pub(super) fn added_rows(&self, page: usize) -> Vec<Row> {
|
||||
let Some(registered) = self.pages.get(page) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let mut rows = Vec::new();
|
||||
registered.rows(&mut rows);
|
||||
rows.into_iter()
|
||||
.enumerate()
|
||||
.map(|(r, row)| self.added_row(page, r, row))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn added_row(&self, page: usize, r: usize, row: added::Row) -> Row {
|
||||
let act = Act::PageRow(page, r);
|
||||
let wide = |label: Text| Row::Buttons(button(0.0, 0.0, 310.0, label, act.clone()), None);
|
||||
match row {
|
||||
added::Row::Heading(key) => Row::Heading(key.to_owned()),
|
||||
added::Row::Note(text) => Row::Note(text),
|
||||
added::Row::Toggle { label, on } => wide(generic(label, on_off(on))),
|
||||
added::Row::Cycle { label, value } => wide(generic(label, label_text(value))),
|
||||
added::Row::Button { label } => wide(tr(label)),
|
||||
added::Row::Key { label, key } => {
|
||||
let mut message = keybinds::display_name(&key);
|
||||
if self.selected_key == Some(PAGE_KEY)
|
||||
&& self.selected_native_key == Some((page, r))
|
||||
{
|
||||
message = Text::literal("> ")
|
||||
.append(message.with_color(text::WHITE))
|
||||
.append(" <")
|
||||
.with_color(text::YELLOW);
|
||||
}
|
||||
let caption = button(0.0, 0.0, 150.0, tr(label), Act::None);
|
||||
let change = button(0.0, 0.0, 150.0, message, act);
|
||||
Row::Buttons(inactive(caption), Some(change))
|
||||
}
|
||||
// A row kind newer than this engine: shown empty.
|
||||
_ => Row::Note(String::new()),
|
||||
}
|
||||
}
|
||||
|
||||
/// A registered page's row was pressed: a key row waits for a key, any other row hears it.
|
||||
pub(super) fn page_act(&mut self, page: usize, r: usize, shift: bool) -> Vec<Event> {
|
||||
let Some(registered) = self.pages.get(page) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let mut rows = Vec::new();
|
||||
registered.rows(&mut rows);
|
||||
match rows.get(r) {
|
||||
Some(added::Row::Key { .. }) => {
|
||||
self.selected_key = Some(PAGE_KEY);
|
||||
self.selected_native_key = Some((page, r));
|
||||
Vec::new()
|
||||
}
|
||||
Some(_) => {
|
||||
registered.act(
|
||||
r,
|
||||
if shift {
|
||||
added::Act::PressBack
|
||||
} else {
|
||||
added::Act::Press
|
||||
},
|
||||
);
|
||||
vec![Event::Changed]
|
||||
}
|
||||
None => Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// A native mod's page: its name, its keys as Key Binds rows (the
|
||||
/// player's choice, else the default), then its buttons.
|
||||
pub(super) fn native_rows(&self, s: &Settings, i: usize) -> Vec<Row> {
|
||||
let Some(m) = s.mods.installed.get(i) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let mut rows = vec![Row::Note(m.title.clone())];
|
||||
let Some(page) = &m.native else {
|
||||
return rows;
|
||||
};
|
||||
let chosen = s.mods.keys.get(&m.id);
|
||||
for (k, [name, label, default]) in page.keys.iter().enumerate() {
|
||||
let key = chosen.and_then(|c| c.get(name)).unwrap_or(default);
|
||||
let mut message = keybinds::display_name(key);
|
||||
if self.selected_native_key == Some((i, k)) {
|
||||
message = Text::literal("> ")
|
||||
.append(message.with_color(text::WHITE))
|
||||
.append(" <")
|
||||
.with_color(text::YELLOW);
|
||||
}
|
||||
let caption = button(0.0, 0.0, 150.0, Text::literal(label.clone()), Act::None);
|
||||
let change = button(0.0, 0.0, 150.0, message, Act::NativeKey(i, k));
|
||||
rows.push(Row::Buttons(inactive(caption), Some(change)));
|
||||
}
|
||||
for (b, label) in page.buttons.iter().enumerate() {
|
||||
let widget = button(
|
||||
0.0,
|
||||
0.0,
|
||||
310.0,
|
||||
Text::literal(label.clone()),
|
||||
Act::NativeButton(i, b),
|
||||
);
|
||||
rows.push(Row::Buttons(widget, None));
|
||||
}
|
||||
rows
|
||||
}
|
||||
|
||||
/// A native mod's key waits for the next key or button pressed.
|
||||
pub(super) fn wait_native_key(&mut self, i: usize, k: usize) {
|
||||
self.selected_key = Some(NATIVE_KEY);
|
||||
self.selected_native_key = Some((i, k));
|
||||
}
|
||||
|
||||
/// The key pressed for the native mod's key, or the registered page's ([`PAGE_KEY`]), that
|
||||
/// waited for one.
|
||||
pub(super) fn bind_native_key(
|
||||
&mut self,
|
||||
s: &mut Settings,
|
||||
name: &str,
|
||||
value: String,
|
||||
) -> Vec<Event> {
|
||||
let (i, k) = self.selected_native_key.take().unwrap_or_default();
|
||||
if name == PAGE_KEY {
|
||||
if let Some(page) = self.pages.get(i) {
|
||||
page.act(k, added::Act::Bind(value));
|
||||
}
|
||||
return vec![Event::Changed];
|
||||
}
|
||||
let Some(m) = s.mods.installed.get(i) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let Some([key, ..]) = m.native.as_ref().and_then(|p| p.keys.get(k)) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let keys = s.mods.keys.entry(m.id.clone()).or_default();
|
||||
keys.insert(key.clone(), value);
|
||||
vec![Event::Changed]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::sync::Mutex;
|
||||
|
||||
/// A page with a heading, a switch, a number that steps either way and a key.
|
||||
struct Sample {
|
||||
on: Mutex<bool>,
|
||||
step: Mutex<i32>,
|
||||
key: Mutex<String>,
|
||||
}
|
||||
|
||||
impl added::Page for Sample {
|
||||
fn id(&self) -> &'static str {
|
||||
"test.sample"
|
||||
}
|
||||
fn title(&self) -> &'static str {
|
||||
"test.sample.title"
|
||||
}
|
||||
fn place(&self) -> added::Place {
|
||||
added::Place::HorizonSettings
|
||||
}
|
||||
fn rows(&self, rows: &mut Vec<added::Row>) {
|
||||
rows.push(added::Row::Heading("test.sample.heading"));
|
||||
rows.push(added::Row::Toggle {
|
||||
label: "test.sample.switch",
|
||||
on: *self.on.lock().unwrap(),
|
||||
});
|
||||
rows.push(added::Row::Cycle {
|
||||
label: "test.sample.step",
|
||||
value: added::Label::Value(self.step.lock().unwrap().to_string()),
|
||||
});
|
||||
rows.push(added::Row::Key {
|
||||
label: "test.sample.key",
|
||||
key: self.key.lock().unwrap().clone(),
|
||||
});
|
||||
}
|
||||
fn act(&self, row: usize, act: added::Act) {
|
||||
match (row, act) {
|
||||
(1, added::Act::Press) => {
|
||||
let mut on = self.on.lock().unwrap();
|
||||
*on = !*on;
|
||||
}
|
||||
(2, added::Act::Press) => *self.step.lock().unwrap() += 1,
|
||||
(2, added::Act::PressBack) => *self.step.lock().unwrap() -= 1,
|
||||
(3, added::Act::Bind(key)) => *self.key.lock().unwrap() = key,
|
||||
other => panic!("row and act the page doesn't expect: {other:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SAMPLE: Sample = Sample {
|
||||
on: Mutex::new(false),
|
||||
step: Mutex::new(0),
|
||||
key: Mutex::new(String::new()),
|
||||
};
|
||||
static PAGES: [&dyn added::Page; 1] = [&SAMPLE];
|
||||
|
||||
/// Clicks the active button that does `act`, with Shift held or not.
|
||||
fn press(ui: &mut OptionsUi, s: &mut Settings, act: Act, shift: bool) -> Vec<Event> {
|
||||
let size = (480.0, 240.0);
|
||||
let (widgets, ..) = ui.layout(s, size.0, size.1);
|
||||
let (x, y) = widgets
|
||||
.iter()
|
||||
.find_map(|w| match &w.kind {
|
||||
WKind::Button {
|
||||
act: a,
|
||||
active: true,
|
||||
..
|
||||
} if *a == act => Some((w.x + 1.0, w.y + 1.0)),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| panic!("no button does {act:?}"));
|
||||
ui.shift = shift;
|
||||
let atlas = super::super::tests::atlas();
|
||||
ui.click(s, &atlas, x, y, size, [480, 240], false, false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_registered_page_opens_from_horizon_settings_and_hears_its_rows() {
|
||||
let mut s = Settings::default();
|
||||
let mut ui = OptionsUi {
|
||||
pages: &PAGES,
|
||||
..OptionsUi::default()
|
||||
};
|
||||
ui.show(Page::Horizon);
|
||||
press(&mut ui, &mut s, Act::Push(Page::Added(0)), false);
|
||||
assert_eq!(ui.page(), Page::Added(0));
|
||||
// Rows: the heading (0), the switch (1), the step (2), the key (3).
|
||||
let events = press(&mut ui, &mut s, Act::PageRow(0, 1), false);
|
||||
assert_eq!(
|
||||
events.last(),
|
||||
Some(&Event::Changed),
|
||||
"the settings get saved"
|
||||
);
|
||||
assert!(*SAMPLE.on.lock().unwrap());
|
||||
press(&mut ui, &mut s, Act::PageRow(0, 2), false);
|
||||
press(&mut ui, &mut s, Act::PageRow(0, 2), true);
|
||||
press(&mut ui, &mut s, Act::PageRow(0, 2), true);
|
||||
assert_eq!(*SAMPLE.step.lock().unwrap(), -1, "Shift steps back");
|
||||
// A key row waits for the next key, as on Key Binds, and the page gets its name.
|
||||
press(&mut ui, &mut s, Act::PageRow(0, 3), false);
|
||||
let atlas = super::super::tests::atlas();
|
||||
let events = ui.key(&mut s, &atlas, winit::keyboard::KeyCode::KeyZ, None);
|
||||
assert_eq!(events, [Event::Changed]);
|
||||
assert_eq!(*SAMPLE.key.lock().unwrap(), "key.keyboard.z");
|
||||
assert_eq!(ui.selected_key, None);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
//! `redstone.<power>`), for drawing only: the pack recolours collars, tropical fish, banners, wool,
|
||||
//! sign text and redstone wire and dust, while gameplay (crafting, item data, the beacon) keeps
|
||||
//! vanilla's `DyeColor`. Lock-free: the draw paths and the mesher's workers read it per face.
|
||||
use std::path::Path;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::atomic::{AtomicU64, Ordering::Relaxed};
|
||||
|
||||
use crate::block_entity_render::DYES;
|
||||
@@ -30,6 +32,96 @@ pub fn set(colors: &PackColors) {
|
||||
}
|
||||
}
|
||||
|
||||
/// An item modifier's `bar_color` of the `damage` type: a row of colours picked by the stack's
|
||||
/// damage, the first pixel undamaged, the last at full damage (measured on the real mod).
|
||||
struct DamageBar {
|
||||
targets: horizon_polytone::Targets,
|
||||
row: Vec<u32>,
|
||||
}
|
||||
static ITEM_BARS: RwLock<Vec<DamageBar>> = RwLock::new(Vec::new());
|
||||
|
||||
/// Reads the packs' item modifiers' durability bar colours under a pack overlay root: an
|
||||
/// `<item>_bar.png` alone, or a json whose `bar_color` is `damage` with its `<name>_bar.png` (or
|
||||
/// `<name>.png`) beside it. Colormap ids and inline colormaps aren't read.
|
||||
pub fn set_item_bars(root: &Path) {
|
||||
let mut bars = Vec::new();
|
||||
for namespace in std::fs::read_dir(root.join("assets"))
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flatten()
|
||||
{
|
||||
let base = namespace.path().join("polytone/item_modifiers");
|
||||
let mut stack = vec![base.clone()];
|
||||
while let Some(dir) = stack.pop() {
|
||||
for entry in std::fs::read_dir(&dir).into_iter().flatten().flatten() {
|
||||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
stack.push(path);
|
||||
} else if let Some(bar) = item_bar(root, &base, &path) {
|
||||
bars.push(bar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*ITEM_BARS.write().unwrap_or_else(|e| e.into_inner()) = bars;
|
||||
}
|
||||
|
||||
fn item_bar(root: &Path, base: &Path, path: &Path) -> Option<DamageBar> {
|
||||
let name = path.file_name()?.to_str()?;
|
||||
let row = |png: &Path| {
|
||||
let (width, _, rgba) = crate::sprites::read_rgba(png).ok()?;
|
||||
let row: Vec<u32> = rgba[..width as usize * 4]
|
||||
.as_chunks::<4>()
|
||||
.0
|
||||
.iter()
|
||||
.map(|p| u32::from(p[0]) << 16 | u32::from(p[1]) << 8 | u32::from(p[2]))
|
||||
.collect();
|
||||
(!row.is_empty()).then_some(row)
|
||||
};
|
||||
if let Some(stem) = name.strip_suffix("_bar.png") {
|
||||
// A json of the same name owns its png.
|
||||
if path.with_file_name(format!("{stem}.json")).exists() {
|
||||
return None;
|
||||
}
|
||||
let relative = path.parent()?.strip_prefix(base).ok()?.join(stem);
|
||||
let namespace = base.parent()?.parent()?.file_name()?.to_str()?;
|
||||
let id = format!("{namespace}:{}", relative.to_str()?.replace('\\', "/"));
|
||||
let targets = horizon_polytone::Targets::parse(None, Some(&id)).ok()?;
|
||||
return Some(DamageBar {
|
||||
targets,
|
||||
row: row(path)?,
|
||||
});
|
||||
}
|
||||
let stem = name.strip_suffix(".json")?;
|
||||
let json: serde_json::Value = horizon_world::json_file::read(path).ok()?;
|
||||
if json.get("bar_color")?.as_str()? != "damage" {
|
||||
return None;
|
||||
}
|
||||
let png = [format!("{stem}_bar.png"), format!("{stem}.png")]
|
||||
.into_iter()
|
||||
.map(|png| path.with_file_name(png))
|
||||
.find(|png| png.exists())?;
|
||||
let relative = path.strip_prefix(root).unwrap_or(path).to_string_lossy();
|
||||
let implicit = horizon_polytone::implicit_id(&relative, "item_modifiers");
|
||||
let targets =
|
||||
horizon_polytone::Targets::parse(json.get("targets"), implicit.as_deref()).ok()?;
|
||||
Some(DamageBar {
|
||||
targets,
|
||||
row: row(&png)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// A pack's durability bar colour (RGB) for an item at this damage (0 to 1).
|
||||
pub fn item_bar_color(item: &str, damage: f32) -> Option<u32> {
|
||||
let bars = ITEM_BARS.read().unwrap_or_else(|e| e.into_inner());
|
||||
let bar = bars
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|b| b.targets.matches(item, |_| false))?;
|
||||
let last = (bar.row.len() - 1) as f32;
|
||||
Some(bar.row[(damage.clamp(0.0, 1.0) * last).round() as usize])
|
||||
}
|
||||
|
||||
fn read(table: &[AtomicU64; 16], i: usize) -> Option<u32> {
|
||||
let v = table[i & 15].load(Relaxed);
|
||||
(v != 0).then_some(v as u32)
|
||||
@@ -96,4 +188,49 @@ mod tests {
|
||||
assert_eq!(sheep_wool(pink as u8), 0xB6687F);
|
||||
std::fs::remove_dir_all(&dir).ok();
|
||||
}
|
||||
|
||||
fn png_row(path: &Path, pixels: &[[u8; 3]]) {
|
||||
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
|
||||
let file = std::fs::File::create(path).unwrap();
|
||||
let mut encoder = png::Encoder::new(file, pixels.len() as u32, 1);
|
||||
encoder.set_color(png::ColorType::Rgba);
|
||||
let data: Vec<u8> = pixels
|
||||
.iter()
|
||||
.flat_map(|p| [p[0], p[1], p[2], 255])
|
||||
.collect();
|
||||
encoder
|
||||
.write_header()
|
||||
.unwrap()
|
||||
.write_image_data(&data)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_damage_bar_picks_its_pixel_by_the_stacks_damage() {
|
||||
let dir = std::env::temp_dir().join(format!("pack-bars-{}", std::process::id()));
|
||||
let modifiers = dir.join("assets/minecraft/polytone/item_modifiers");
|
||||
let rgby = [[255, 0, 0], [0, 255, 0], [0, 0, 255], [255, 255, 0]];
|
||||
png_row(&modifiers.join("diamond_pickaxe_bar.png"), &rgby);
|
||||
std::fs::write(
|
||||
modifiers.join("tools.json"),
|
||||
r#"{"targets": ["minecraft:iron_axe"], "bar_color": "damage"}"#,
|
||||
)
|
||||
.unwrap();
|
||||
png_row(&modifiers.join("tools_bar.png"), &[[1, 2, 3], [4, 5, 6]]);
|
||||
set_item_bars(&dir);
|
||||
// The real mod: damage 200 of 1561 shows the first pixel, 1400 the last.
|
||||
assert_eq!(
|
||||
item_bar_color("minecraft:diamond_pickaxe", 200.0 / 1561.0),
|
||||
Some(0xFF0000)
|
||||
);
|
||||
assert_eq!(
|
||||
item_bar_color("minecraft:diamond_pickaxe", 1400.0 / 1561.0),
|
||||
Some(0xFFFF00)
|
||||
);
|
||||
assert_eq!(item_bar_color("minecraft:iron_axe", 0.9), Some(0x040506));
|
||||
assert_eq!(item_bar_color("minecraft:diamond_shovel", 0.5), None);
|
||||
set_item_bars(&dir.join("none"));
|
||||
assert_eq!(item_bar_color("minecraft:diamond_pickaxe", 0.5), None);
|
||||
std::fs::remove_dir_all(&dir).ok();
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
//! Horizon Settings > PvP & HUD. Every option is off by default, so the game looks like
|
||||
//! vanilla until the player changes one, and none of them shows anything vanilla doesn't
|
||||
//! already tell the player.
|
||||
use horizon_hooks::look::Look;
|
||||
|
||||
/// Colours the PvP options pick from. `Inverted` is vanilla's crosshair blend: the colour
|
||||
/// under it, inverted.
|
||||
@@ -263,15 +264,6 @@ impl ViewWeather {
|
||||
Self::ALL.into_iter().find(|c| c.name() == s)
|
||||
}
|
||||
}
|
||||
/// The day time this player sees with `fixed` set: the same day (the moon's phase follows the
|
||||
/// world's), at that time.
|
||||
pub fn view_day_time(world: i64, fixed: Option<ViewTime>) -> i64 {
|
||||
match fixed {
|
||||
Some(t) => world.div_euclid(24000) * 24000 + t.day_time(),
|
||||
None => world,
|
||||
}
|
||||
}
|
||||
|
||||
/// The crosshair's look. Its defaults draw vanilla's: a 15-pixel cross, one pixel thick,
|
||||
/// inverting what is under it.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
@@ -528,24 +520,36 @@ impl Hit {
|
||||
}
|
||||
}
|
||||
|
||||
/// What the renderer reads of these options each frame (`FrameInputs::pvp`); the default is
|
||||
/// vanilla's look.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
pub struct Frame {
|
||||
/// The block outline's stroke ([`Outline::stroke`]).
|
||||
pub outline: Option<(u32, f32)>,
|
||||
/// The hurt overlay texel ([`Hit::texel`]), 0 for vanilla's.
|
||||
pub hurt_texel: u32,
|
||||
/// The glint's colour ([`Tweaks::glint_texel`]), 0 for vanilla's.
|
||||
pub glint: u32,
|
||||
}
|
||||
impl Pvp {
|
||||
pub fn frame(&self) -> Frame {
|
||||
Frame {
|
||||
outline: self.outline.stroke(),
|
||||
hurt_texel: self.hit.texel(),
|
||||
glint: self.tweaks.glint_texel(),
|
||||
}
|
||||
/// What the engine reads of these options (`horizon_hooks::look`): all it draws differently.
|
||||
/// Sets PvP & HUD's fields of `look`, the others' stay.
|
||||
pub fn apply(&self, look: &mut Look) {
|
||||
let (c, t) = (self.combat, self.tweaks);
|
||||
look.legacy_pose = c.legacy;
|
||||
look.hide_attack_indicator = c.legacy && !c.indicator;
|
||||
look.mute_attack_sounds = c.legacy && c.sounds;
|
||||
look.hide_attack_particles = c.legacy;
|
||||
look.frame.outline = self.outline.stroke();
|
||||
look.frame.hurt_texel = self.hit.texel();
|
||||
look.frame.glint = t.glint_texel();
|
||||
look.shield_size = t.shield_size;
|
||||
look.totem_scale = f32::from(t.totem_size) / 100.0;
|
||||
look.fire_lower = f32::from(t.fire_lower) / 100.0;
|
||||
look.clear_lava = t.clear_lava;
|
||||
look.clear_water = t.clear_water;
|
||||
look.chat.timestamps = self.chat.timestamps;
|
||||
look.chat.compact = self.chat.compact;
|
||||
look.chat.copy = self.chat.copy;
|
||||
look.chat.search = self.chat.search;
|
||||
look.hide_effect_icons = self.hud.effects;
|
||||
look.time_of_day = t.time.map(ViewTime::day_time);
|
||||
look.weather = t.weather.map(ViewWeather::levels);
|
||||
}
|
||||
/// [`Pvp::apply`] on vanilla's look.
|
||||
pub fn look(&self) -> Look {
|
||||
let mut look = Look::default();
|
||||
self.apply(&mut look);
|
||||
look
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,15 +745,6 @@ pub struct ChatOptions {
|
||||
/// Ctrl+F in the chat searches the chat's messages.
|
||||
pub search: bool,
|
||||
}
|
||||
impl ChatOptions {
|
||||
/// What `chat::Chat` lays its lines out with.
|
||||
pub fn qol(&self) -> crate::chat::ChatQol {
|
||||
crate::chat::ChatQol {
|
||||
timestamps: self.timestamps,
|
||||
compact: self.compact,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Combat feel (`docs/pvp.md`): how fights look. Legacy draws them as 1.8.9 did; what the
|
||||
/// game sends to a server never changes, so a vanilla server and its anticheat see 26.3.
|
||||
@@ -766,21 +761,6 @@ pub struct Combat {
|
||||
/// (`horizon_client::legacy_combat`). Never used as a client of a server.
|
||||
pub rules: bool,
|
||||
}
|
||||
impl Combat {
|
||||
/// Whether this client leaves out sound `name` a server sent: under Legacy with its
|
||||
/// sounds, the `entity.player.attack.*` family (strong, weak, crit, sweep, knockback,
|
||||
/// nodamage), which 1.9 brought with the attack cooldown.
|
||||
pub fn mutes_sound(&self, name: &str) -> bool {
|
||||
let name = name.strip_prefix("minecraft:").unwrap_or(name);
|
||||
self.legacy && self.sounds && name.starts_with("entity.player.attack.")
|
||||
}
|
||||
/// Whether this client leaves out particles of `ty` a server sent: under Legacy, the
|
||||
/// sweep and the damage hearts, which 1.9 brought (1.8.9's hits show crits only).
|
||||
pub fn hides_particle(&self, ty: crate::particles::ParticleType) -> bool {
|
||||
use crate::particles::ParticleType as T;
|
||||
self.legacy && matches!(ty, T::SweepAttack | T::DamageIndicator)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Pvp {
|
||||
@@ -1707,18 +1687,6 @@ mod tests {
|
||||
assert_eq!(fresh.extras.pvp.tweaks.fire_lower, PRESET_FIRE_LOWER);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_fixed_time_keeps_the_worlds_day() {
|
||||
// Day 9 at 5000: the moon's phase (the day number) stays, the time of day is the chosen.
|
||||
let world = 9 * 24000 + 5000;
|
||||
assert_eq!(view_day_time(world, None), world);
|
||||
assert_eq!(
|
||||
view_day_time(world, Some(ViewTime::Midnight)),
|
||||
9 * 24000 + 18000
|
||||
);
|
||||
assert_eq!(view_day_time(-100, Some(ViewTime::Noon)), -24000 + 6000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_glint_colour_reaches_the_shaders_as_rgb_bytes() {
|
||||
let mut t = Tweaks::default();
|
||||
@@ -1805,31 +1773,33 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// Legacy leaves out what 1.9 added to a hit: its sounds only with the sounds option, the
|
||||
/// sweep and hearts always; the indicator stays when kept. Modern changes nothing.
|
||||
#[test]
|
||||
fn legacy_leaves_out_what_1_9_added_to_a_hit() {
|
||||
use crate::particles::ParticleType as T;
|
||||
let modern = Combat::default();
|
||||
let legacy = Combat {
|
||||
legacy: true,
|
||||
..Combat::default()
|
||||
};
|
||||
let sounds = Combat {
|
||||
sounds: true,
|
||||
..legacy
|
||||
};
|
||||
for name in [
|
||||
"minecraft:entity.player.attack.strong",
|
||||
"entity.player.attack.sweep",
|
||||
"minecraft:entity.player.attack.nodamage",
|
||||
] {
|
||||
assert!(sounds.mutes_sound(name), "{name}");
|
||||
assert!(!legacy.mutes_sound(name), "only with the sounds option");
|
||||
assert!(!modern.mutes_sound(name));
|
||||
}
|
||||
// 1.8.9 had the hurt sound: it stays.
|
||||
assert!(!sounds.mutes_sound("minecraft:entity.player.hurt"));
|
||||
assert!(legacy.hides_particle(T::SweepAttack) && legacy.hides_particle(T::DamageIndicator));
|
||||
assert!(!legacy.hides_particle(T::Crit) && !legacy.hides_particle(T::EnchantedHit));
|
||||
assert!(!modern.hides_particle(T::SweepAttack));
|
||||
fn combat_feel_reaches_the_look() {
|
||||
let mut pvp = Pvp::default();
|
||||
assert_eq!(pvp.look(), Look::default(), "vanilla's look");
|
||||
let strong = "minecraft:entity.player.attack.strong";
|
||||
pvp.combat.legacy = true;
|
||||
let look = pvp.look();
|
||||
assert!(look.legacy_pose && look.hide_attack_particles && look.hide_attack_indicator);
|
||||
assert!(!look.mutes_sound(strong), "only with the sounds option");
|
||||
pvp.combat.sounds = true;
|
||||
pvp.combat.indicator = true;
|
||||
let look = pvp.look();
|
||||
assert!(look.mutes_sound(strong) && !look.hide_attack_indicator);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn view_time_weather_and_sizes_reach_the_look() {
|
||||
let mut pvp = Pvp::default();
|
||||
pvp.tweaks.time = Some(ViewTime::Midnight);
|
||||
pvp.tweaks.weather = Some(ViewWeather::Thunder);
|
||||
pvp.tweaks.totem_size = 50;
|
||||
pvp.tweaks.fire_lower = 40;
|
||||
let look = pvp.look();
|
||||
assert_eq!(look.day_time(9 * 24000 + 5000), 9 * 24000 + 18000);
|
||||
assert_eq!(look.weather, Some((1.0, 1.0)));
|
||||
assert_eq!((look.totem_scale, look.fire_lower), (0.5, 0.4));
|
||||
}
|
||||
}
|
||||
@@ -337,6 +337,13 @@ impl Settings {
|
||||
.and_then(|mode| self.video_modes.iter().position(|m| *m == mode))
|
||||
.map_or(-1, |i| i as i32)
|
||||
}
|
||||
/// Loads only the crates' settings stores (`horizon_hooks::settings`) from the files next to
|
||||
/// `path`, into the seat whose turn it is (`horizon_hooks::seat`): a splitscreen player whose
|
||||
/// settings were made from P1's rather than loaded.
|
||||
pub fn load_stores(path: &Path) {
|
||||
let dir = path.parent();
|
||||
horizon_hooks::settings::engine::load(&mut |file| fs::read_to_string(dir?.join(file)).ok());
|
||||
}
|
||||
pub fn load(path: &Path) -> Self {
|
||||
let mut horizon = path
|
||||
.parent()
|
||||
@@ -362,6 +369,13 @@ impl Settings {
|
||||
.and_then(|dir| fs::read_to_string(dir.join(crate::extras::FILE)).ok())
|
||||
.unwrap_or_default();
|
||||
let mut extras = crate::extras::Extras::parse(&extras_text);
|
||||
// The settings stores of the crates above the engine: their lines of this file, or of
|
||||
// their own (docs/layers.md, "Platform registries").
|
||||
horizon_hooks::settings::engine::load(&mut |file| match path.parent() {
|
||||
_ if file == crate::extras::FILE => Some(extras_text.clone()),
|
||||
Some(dir) => fs::read_to_string(dir.join(file)).ok(),
|
||||
None => None,
|
||||
});
|
||||
// The enabled mods are the game folder's, shared by its players (`--player-dir`).
|
||||
let mods = path
|
||||
.parent()
|
||||
@@ -690,6 +704,7 @@ impl Settings {
|
||||
let mut extras = self.extras.clone();
|
||||
extras.emote_key = self.keys.get("key.emote").to_owned();
|
||||
extras.save(dir);
|
||||
horizon_hooks::settings::engine::save_own(dir, &[crate::extras::FILE]);
|
||||
self.mods.save(&crate::logging::shared_dir(dir));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,6 +549,9 @@ pub struct Streaming {
|
||||
pub mod_forced: HashSet<(i32, i32)>,
|
||||
/// No work is scheduled while paused (title screen).
|
||||
pub paused: bool,
|
||||
/// Finished meshes the renderer has not taken yet (the game's pending
|
||||
/// uploads): they count against the meshing room as the jobs do.
|
||||
pub upload_backlog: usize,
|
||||
/// Dimension flags: sky light, Nether face shading.
|
||||
pub sky_light: bool,
|
||||
pub nether_shading: bool,
|
||||
@@ -1062,7 +1065,9 @@ pub struct WorkerContext {
|
||||
pub biomes: Arc<crate::biome::Biomes>,
|
||||
pub light: Arc<LightTables>,
|
||||
}
|
||||
mod bounded;
|
||||
mod relight_now;
|
||||
use bounded::nearest_first;
|
||||
impl Streaming {
|
||||
pub fn new<G: ChunkGenerator>(
|
||||
generator: Arc<G>,
|
||||
@@ -1147,6 +1152,7 @@ impl Streaming {
|
||||
forced: HashSet::new(),
|
||||
mod_forced: HashSet::new(),
|
||||
paused: false,
|
||||
upload_backlog: 0,
|
||||
sky_light: true,
|
||||
nether_shading: false,
|
||||
shader_pack_lighting: false,
|
||||
@@ -2083,7 +2089,10 @@ impl Streaming {
|
||||
// jobs went stale long before a worker reached them (#3629). What
|
||||
// stays dirty is asked for again, from the current centre, as
|
||||
// capacity frees; `requeue` then has a small queue to keep close.
|
||||
let room = (self.workers * 32).saturating_sub(self.meshing.len());
|
||||
// Meshes waiting for upload count too: when uploads fall behind (a
|
||||
// low frame rate at a wide distance), meshing on held gigabytes of
|
||||
// them until the system swapped.
|
||||
let room = (self.workers * 32).saturating_sub(self.meshing.len() + self.upload_backlog);
|
||||
nearest_first(&mut candidates, room);
|
||||
for (_, x, z, sections) in candidates.drain(..) {
|
||||
let Some(region) = Self::region(world, x, z) else {
|
||||
@@ -3021,19 +3030,6 @@ fn light_region_ready(
|
||||
}
|
||||
true
|
||||
}
|
||||
/// The nearest `room` of the `candidates`, ordered: the light and mesh
|
||||
/// stages submit bounded work, chosen from everything that is ready each
|
||||
/// `update`, so what runs is always the nearest of what is left — chosen
|
||||
/// again, from the current centre, as capacity frees, the way vanilla's
|
||||
/// chunk task queues follow the current ticket levels. The selection is
|
||||
/// O(n); the sort orders only what is submitted.
|
||||
fn nearest_first<T: Ord>(candidates: &mut Vec<T>, room: usize) {
|
||||
if candidates.len() > room {
|
||||
candidates.select_nth_unstable(room);
|
||||
candidates.truncate(room);
|
||||
}
|
||||
candidates.sort_unstable();
|
||||
}
|
||||
/// What `keep_unchanged_sections` found changed.
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
struct Resent {
|
||||
@@ -3586,37 +3582,6 @@ mod tests {
|
||||
assert_eq!(pops(queue), [None]);
|
||||
}
|
||||
|
||||
/// The light and mesh stages submit bounded work, the nearest first:
|
||||
/// what exceeds the room stays dirty, to be chosen again — from the
|
||||
/// current centre — as capacity frees. Submitted whole, the queue once
|
||||
/// held every ready column's jobs and grew with the render distance
|
||||
/// (#3629); ties break by position, so the choice is deterministic.
|
||||
#[test]
|
||||
fn bounded_submission_takes_the_nearest_first() {
|
||||
let candidates: Vec<(i64, i32, i32, u32)> = (0..40i32)
|
||||
.map(|i| {
|
||||
let (x, z) = (i / 8 - 2, i % 8 - 3);
|
||||
(
|
||||
i64::from((x - 3).pow(2) + (z - 2).pow(2)),
|
||||
x,
|
||||
z,
|
||||
1 << (i % 24),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let mut expected = candidates.clone();
|
||||
expected.sort_unstable();
|
||||
let mut none = candidates.clone();
|
||||
nearest_first(&mut none, 0);
|
||||
assert!(none.is_empty());
|
||||
let mut nearest = candidates;
|
||||
nearest_first(&mut nearest, 5);
|
||||
assert_eq!(nearest, expected[..5]);
|
||||
let mut past = expected.clone();
|
||||
nearest_first(&mut past, expected.len() + 10);
|
||||
assert_eq!(past, expected);
|
||||
}
|
||||
|
||||
/// What the scheduler counts as ready to light: every neighbour a
|
||||
/// finished column, or a decorated proto chunk past the area — the
|
||||
/// walk `light_region` makes without its snapshot.
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
//! Bounded submission: the light and mesh stages hand the workers only the
|
||||
//! nearest of what is ready.
|
||||
|
||||
/// The nearest `room` of the `candidates`, ordered: the light and mesh
|
||||
/// stages submit bounded work, chosen from everything that is ready each
|
||||
/// `update`, so what runs is always the nearest of what is left — chosen
|
||||
/// again, from the current centre, as capacity frees, the way vanilla's
|
||||
/// chunk task queues follow the current ticket levels. The selection is
|
||||
/// O(n); the sort orders only what is submitted.
|
||||
pub(super) fn nearest_first<T: Ord>(candidates: &mut Vec<T>, room: usize) {
|
||||
if candidates.len() > room {
|
||||
candidates.select_nth_unstable(room);
|
||||
candidates.truncate(room);
|
||||
}
|
||||
candidates.sort_unstable();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// The light and mesh stages submit bounded work, the nearest first:
|
||||
/// what exceeds the room stays dirty, to be chosen again — from the
|
||||
/// current centre — as capacity frees. Submitted whole, the queue once
|
||||
/// held every ready column's jobs and grew with the render distance
|
||||
/// (#3629); ties break by position, so the choice is deterministic.
|
||||
#[test]
|
||||
fn bounded_submission_takes_the_nearest_first() {
|
||||
let candidates: Vec<(i64, i32, i32, u32)> = (0..40i32)
|
||||
.map(|i| {
|
||||
let (x, z) = (i / 8 - 2, i % 8 - 3);
|
||||
(
|
||||
i64::from((x - 3).pow(2) + (z - 2).pow(2)),
|
||||
x,
|
||||
z,
|
||||
1 << (i % 24),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let mut expected = candidates.clone();
|
||||
expected.sort_unstable();
|
||||
let mut none = candidates.clone();
|
||||
nearest_first(&mut none, 0);
|
||||
assert!(none.is_empty());
|
||||
let mut nearest = candidates;
|
||||
nearest_first(&mut nearest, 5);
|
||||
assert_eq!(nearest, expected[..5]);
|
||||
let mut past = expected.clone();
|
||||
nearest_first(&mut past, expected.len() + 10);
|
||||
assert_eq!(past, expected);
|
||||
}
|
||||
}
|
||||
@@ -138,6 +138,10 @@ fn scaling(sprite: &str, r: &Rect) -> NineSlice {
|
||||
| "horizon/jei/button_disabled_v2"
|
||||
| "horizon/jei/button_highlight_v2" => [6; 4],
|
||||
"horizon/jei/search_background_v2" => [6; 4],
|
||||
"horizon/jei/interactive_ingredient_tooltip_background" => [16; 4],
|
||||
"horizon/jei/recipe_preview_background_v2" => [16; 4],
|
||||
"horizon/jei/scrollbar_background_v2" => [6; 4],
|
||||
"horizon/jei/scrollbar_marker_v2" => [2, 2, 2, 1],
|
||||
"gui/sprites/widget/button"
|
||||
| "gui/sprites/widget/button_highlighted"
|
||||
| "gui/sprites/widget/button_disabled" => [3; 4],
|
||||
@@ -806,8 +810,14 @@ fn slider_sprites(hover: bool, active: bool, dragging: bool) -> (&'static str, &
|
||||
slider_sprites_ext(hover, active, false, false, dragging)
|
||||
}
|
||||
|
||||
/// Track and handle sprites: the track outline shows while dragged or focused with
|
||||
/// keyboard navigation (!can_change_value), hovering or editing highlights the handle.
|
||||
/// `AbstractSliderButton.getSprite` and `getHandleSprite`: the track outline
|
||||
/// lights while the slider is focused and its value cannot change
|
||||
/// (`isActive() && isFocused() && !canChangeValue`), the handle while it is
|
||||
/// hovered or its value can change (`isActive() && (isHovered || canChangeValue)`).
|
||||
/// `canChangeValue` is set when the slider is focused with the mouse or Tab and
|
||||
/// flipped by Enter (`setFocused`, `keyPressed`): Horizon's `can_change_value`
|
||||
/// for the keyboard, and a drag for the mouse, which focuses it with the value
|
||||
/// free to change. So a dragged slider keeps its plain track.
|
||||
fn slider_sprites_ext(
|
||||
hover: bool,
|
||||
active: bool,
|
||||
@@ -815,12 +825,13 @@ fn slider_sprites_ext(
|
||||
can_change_value: bool,
|
||||
dragging: bool,
|
||||
) -> (&'static str, &'static str) {
|
||||
let track = if dragging || (active && focused && !can_change_value) {
|
||||
let can_change_value = can_change_value || dragging;
|
||||
let track = if active && focused && !can_change_value {
|
||||
"gui/sprites/widget/slider_highlighted"
|
||||
} else {
|
||||
"gui/sprites/widget/slider"
|
||||
};
|
||||
let handle = if active && (hover || can_change_value || dragging) {
|
||||
let handle = if active && (hover || can_change_value) {
|
||||
"gui/sprites/widget/slider_handle_highlighted"
|
||||
} else {
|
||||
"gui/sprites/widget/slider_handle"
|
||||
@@ -2171,17 +2182,38 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// `AbstractSliderButton.getSprite`/`getHandleSprite`: a focused slider
|
||||
/// whose value can't change lights its track, a hovered one or one whose
|
||||
/// value can change (Tab or Enter, or the mouse's drag) lights its handle.
|
||||
#[test]
|
||||
fn slider_track_is_outlined_only_while_dragged() {
|
||||
fn slider_sprites_follow_focus_and_the_drag() {
|
||||
// Hovered, at rest: plain track, lit handle.
|
||||
let (track, handle) = slider_sprites(true, true, false);
|
||||
assert_eq!(track, "gui/sprites/widget/slider");
|
||||
assert_eq!(handle, "gui/sprites/widget/slider_handle_highlighted");
|
||||
// Dragged: still a plain track, lit handle.
|
||||
let (track, handle) = slider_sprites(true, true, true);
|
||||
assert_eq!(track, "gui/sprites/widget/slider_highlighted");
|
||||
assert_eq!(track, "gui/sprites/widget/slider");
|
||||
assert_eq!(handle, "gui/sprites/widget/slider_handle_highlighted");
|
||||
// Focused with the arrow keys: the value can't change, the track lights.
|
||||
let (track, handle) = slider_sprites_ext(false, true, true, false, false);
|
||||
assert_eq!(track, "gui/sprites/widget/slider_highlighted");
|
||||
assert_eq!(handle, "gui/sprites/widget/slider_handle");
|
||||
// Focused with Tab, or Enter pressed on it: the value can change, the handle lights.
|
||||
let (track, handle) = slider_sprites_ext(false, true, true, true, false);
|
||||
assert_eq!(track, "gui/sprites/widget/slider");
|
||||
assert_eq!(handle, "gui/sprites/widget/slider_handle_highlighted");
|
||||
// Focused while the mouse drags: the track stays plain.
|
||||
let (track, _) = slider_sprites_ext(true, true, true, false, true);
|
||||
assert_eq!(track, "gui/sprites/widget/slider");
|
||||
// Not hovered, not dragged: nothing is lit.
|
||||
let (track, handle) = slider_sprites(false, true, false);
|
||||
assert_eq!(track, "gui/sprites/widget/slider");
|
||||
assert_eq!(handle, "gui/sprites/widget/slider_handle");
|
||||
// An inactive slider highlights neither, even when focused.
|
||||
let (track, handle) = slider_sprites_ext(true, false, true, true, true);
|
||||
assert_eq!(track, "gui/sprites/widget/slider");
|
||||
assert_eq!(handle, "gui/sprites/widget/slider_handle");
|
||||
}
|
||||
#[test]
|
||||
fn separator_tiles_sample_both_rows_and_clip_the_last_column() {
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Lig skaduwees na jou skerm se donkerste swart. 0: suiwer swart, geen ligting.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Hoe helder hoogtepunte word. Outo: die hoogtepunt wat jou stelsel rapporteer.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Hoe helder wit in die wêreld lyk. Outo: jou lessenaar se wit.",
|
||||
"How bright the HUD and menus are, against paper white.": "Hoe helder die HUD en spyskaarte is, teenoor papierwit.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Hoe ver skare, gewasse en masjiene aanhou werk. SVE tyd.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Hoe ver weg skares en items getrek word, as 'n deel van normaal.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Slaan terrein oor wat agter geslote gedeeltes versteek is. Af kos baie.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Gevorderd",
|
||||
"Undo": "Ontdoen",
|
||||
"Search options": "Soek opsies",
|
||||
"Shortcut": "Kortpad",
|
||||
"Distance": "Afstand",
|
||||
"Display": "Vertoon",
|
||||
"Interface": "Koppelvlak",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibreer...",
|
||||
"Calibrate Anyway...": "Kalibreer in elk geval...",
|
||||
"Use Automatic Setup": "Gebruik outomatiese opstelling",
|
||||
"Shortcut: %s": "Kortpad: %s",
|
||||
"Next": "Volgende",
|
||||
"HDR Calibration %s/%s: %s": "HDR-kalibrasie %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Stel die drie hieronder volskerm, een toetsprent op 'n slag.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "'n Sleutel wat hierdie skerm vanaf die speletjie oopmaak. Eers nie gebonde nie.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Jou skerm het nie gesê hoe helder dit word nie: kalibreer om dit op te stel.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Reeds opgestel vir jou vertoning. Kalibreer slegs as HDR verkeerd lyk.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Plaas Peak Brightness en Paper White terug na jou skerm se opstelling.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "يرفع الظلال إلى أغمق أسود في شاشتك. 0: أسود حقيقي، دون رفع.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "كيف تحصل على النقاط البارزة الساطعة. تلقائي: ذروة تقارير النظام الخاص بك.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "مدى سطوع الأبيض في العالم. تلقائي: أبيض سطح المكتب.",
|
||||
"How bright the HUD and menus are, against paper white.": "مدى سطوع شاشة HUD والقوائم مقابل الورق الأبيض.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "إلى أي مدى يستمر الغوغاء والمحاصيل والآلات في العمل. وقت وحدة المعالجة المركزية.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "إلى أي مدى يتم رسم الغوغاء والعناصر، كنسبة من المعدل الطبيعي.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "يتخطى التضاريس المخفية خلف الأقسام المغلقة. قبالة تكاليف الكثير.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "متقدم",
|
||||
"Undo": "تراجع",
|
||||
"Search options": "خيارات البحث",
|
||||
"Shortcut": "الاختصار",
|
||||
"Distance": "المسافة",
|
||||
"Display": "عرض",
|
||||
"Interface": "واجهة",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "معايرة...",
|
||||
"Calibrate Anyway...": "معايرة على أية حال...",
|
||||
"Use Automatic Setup": "استخدم الإعداد التلقائي",
|
||||
"Shortcut: %s": "الاختصار: %s",
|
||||
"Next": "التالي",
|
||||
"HDR Calibration %s/%s: %s": "معايرة HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "لتعيين الصور الثلاثة أدناه بملء الشاشة، صورة اختبارية واحدة في كل مرة.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "المفتاح الذي يفتح هذه الشاشة من اللعبة. غير ملزمة في البداية.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "لم توضح شاشتك مدى سطوعها: قم بالمعايرة لإعدادها.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "تم إعداده بالفعل للعرض الخاص بك. قم بالمعايرة فقط إذا كان تقرير HDR يبدو خاطئًا.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "يعيد ذروة السطوع والورق الأبيض إلى إعداد شاشتك.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Kölgələri ekranınızın ən tünd qarasına qaldırır. 0: həqiqi qara, qaldırma yoxdur.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Parlaq məqamlar necə əldə edilir. Avtomatik: sisteminizin ən yüksək hesabatı.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Dünyada ağ rəngin nə qədər parlaq göründüyü. Avtomatik: iş masanızın ağı.",
|
||||
"How bright the HUD and menus are, against paper white.": "HUD və menyular ağ kağıza qarşı nə qədər parlaqdır.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Kütlələr, məhsullar və maşınlar nə qədər işləməyə davam edir. CPU vaxtı.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Nə qədər uzağa mob və əşyalar çəkilir, normal bir pay olaraq.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Qapalı hissələrin arxasında gizlənmiş ərazini ötür. Sıxılma çox baha başa gəlir.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Qabaqcıl",
|
||||
"Undo": "Geri alın",
|
||||
"Search options": "Axtarış seçimləri",
|
||||
"Shortcut": "Qısayol",
|
||||
"Distance": "Məsafə",
|
||||
"Display": "Ekran",
|
||||
"Interface": "İnterfeys",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibrləmə...",
|
||||
"Calibrate Anyway...": "İstənilən halda kalibrləyin...",
|
||||
"Use Automatic Setup": "Avtomatik Quraşdırmadan istifadə edin",
|
||||
"Shortcut: %s": "Qısayol: %s",
|
||||
"Next": "Sonrakı",
|
||||
"HDR Calibration %s/%s: %s": "HDR Kalibrləmə %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Aşağıdakı üç tam ekranı, hər dəfə bir sınaq şəklini təyin edir.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Oyundan bu ekranı açan açar. Əvvəlcə bağlı deyil.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Ekranınız nə qədər parlaq olduğunu deməyib: onu qurmaq üçün kalibrləyin.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Ekranınız üçün artıq qurulub. Yalnız HDR səhv görünürsə kalibrləyin.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Pik Parlaqlığı və Kağız Ağı ekranınızın quraşdırılmasına qaytarır.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Күләгәләрҙе дисплейығыҙҙың иң ҡара ҡараһына күтәрә. 0: ысын ҡара, күтәреү юҡ.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Нисек сағыу өҫтөнлөктәр ала. Авто: пик һеҙҙең система отчеттар.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Донъяла аҡ ни тиклем сағыу күренә. Авто: эш өҫтәлегеҙҙең ағы.",
|
||||
"How bright the HUD and menus are, against paper white.": "Нисек сағыу HUD һәм менюлар, ҡағыҙ аҡ ҡаршы.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Күпме алыҫҡа мобтар, культуралар һәм машиналар эшләп тора. Процессор ваҡыты.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Нисек алыҫҡа мобтар һәм әйберҙәр тартыла, өлөшө булараҡ нормаль.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Ябыҡ участкалар артында йәшеренгән ерҙәрҙе һикерә. Офф күп сығымдар талап итә.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Алдынғы",
|
||||
"Undo": "Кире ҡайтарыу",
|
||||
"Search options": "Эҙләү варианттары",
|
||||
"Shortcut": "Ярлыҡ",
|
||||
"Distance": "Арауыҡ",
|
||||
"Display": "Дисплей",
|
||||
"Interface": "Интерфейс",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Калибрлау...",
|
||||
"Calibrate Anyway...": "Калибрлау барыбер...",
|
||||
"Use Automatic Setup": "Автоматик ҡуйыуҙы ҡулланыу",
|
||||
"Shortcut: %s": "Ҡыҫҡа юл: %s",
|
||||
"Next": "Артабан",
|
||||
"HDR Calibration %s/%s: %s": "HDR калибровкаһы %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Өс аҫтында тулы экран ҡуя, бер һынау һүрәте бер юлы.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Уйындан был экранды асҡан асҡыс. Тәүҙә бәйләнмәгән.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Һеҙҙең дисплей нисек яҡты ала, тип әйтмәне: калибровка, уны ҡуйырға.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Һеҙҙең дисплей өсөн инде ҡуйылған. Тик калибровка, әгәр HDR дөрөҫ түгел күренә.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Ҡуя Пик Яркость һәм Ҡағыҙ Аҡ кире һеҙҙең дисплей’ы ҡороу.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Падымае цені да самага цёмнага чорнага вашага дысплея. 0: сапраўдны чорны, без пад'ёму.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Якія яркія моманты становяцца. Аўта: пік, пра які паведамляе ваша сістэма.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Наколькі ярка выглядае белы ў свеце. Аўто: белы колер вашага працоўнага стала.",
|
||||
"How bright the HUD and menus are, against paper white.": "Наколькі яркія HUD і меню на фоне белай паперы.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Як далёка працягваюць працаваць мобы, ураджай і машыны. працэсарны час.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Наколькі далёка намаляваны мобы і прадметы ў долі звычайнага.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Прапускае мясцовасць, схаваную за закрытымі ўчасткамі. Off каштуе шмат.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Пашыраны",
|
||||
"Undo": "Адмяніць",
|
||||
"Search options": "Параметры пошуку",
|
||||
"Shortcut": "Ярлык",
|
||||
"Distance": "Дыстанцыя",
|
||||
"Display": "Дысплей",
|
||||
"Interface": "Інтэрфейс",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Адкалібраваць...",
|
||||
"Calibrate Anyway...": "Усё роўна адкалібраваць...",
|
||||
"Use Automatic Setup": "Выкарыстоўвайце аўтаматычную наладу",
|
||||
"Shortcut: %s": "Ярлык: %s",
|
||||
"Next": "Далей",
|
||||
"HDR Calibration %s/%s: %s": "Каліброўка HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Устанаўлівае тры ніжэй на ўвесь экран, па адным тэставым малюнку.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Ключ, які адкрывае гэты экран з гульні. Спачатку не звязаны.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "На вашым дысплеі не пазначана, наколькі ён яркім: адкалібруйце, каб наладзіць яго.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Ужо наладжана для вашага дысплея. Калібруйце, толькі калі HDR выглядае няправільна.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Вяртае пікавую яркасць і папяровы белы ў налады вашага дысплея.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Повдига сенките до най-тъмното черно на вашия дисплей. 0: истинско черно, без повдигане.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Колко ярки стават акцентите. Автоматично: пикът, който вашата система отчита.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Колко ярко изглежда бялото в света. Авто: бялото на вашия работен плот.",
|
||||
"How bright the HUD and menus are, against paper white.": "Колко ярки са HUD и менютата на бяла хартия.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Докъде продължават да работят тълпите, културите и машините. процесорно време.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Колко далеч са изтеглени тълпите и предметите, като дял от нормалното.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Пропуска терен, скрит зад затворени участъци. Off струва много.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Разширено",
|
||||
"Undo": "Отмяна",
|
||||
"Search options": "Опции за търсене",
|
||||
"Shortcut": "Пряк път",
|
||||
"Distance": "Разстояние",
|
||||
"Display": "Дисплей",
|
||||
"Interface": "Интерфейс",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Калибриране...",
|
||||
"Calibrate Anyway...": "Калибриране все пак...",
|
||||
"Use Automatic Setup": "Използвайте автоматична настройка",
|
||||
"Shortcut: %s": "Пряк път: %s",
|
||||
"Next": "Следваща",
|
||||
"HDR Calibration %s/%s: %s": "HDR калибриране %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Задава трите под цял екран, една тестова картина наведнъж.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Ключ, който отваря този екран от играта. В началото не е обвързан.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Вашият дисплей не каза колко ярък става: калибрирайте, за да го настроите.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Вече е настроен за вашия дисплей. Калибрирайте само ако HDR изглежда грешно.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Връща Peak Brightness и Paper White обратно към настройката на вашия дисплей.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Sevel a ra ar skeudoù betek du teñvalañ ho skramm. 0 : du gwir, sevel ebet.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Pegen skedus e teu ar sklêrijennoù. Emgefre : ar pik a vez embannet gant ho reizhiad.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Pegen skedus e seblant ar gwenn er bed. Emgefreek : gwenn ho kefridi.",
|
||||
"How bright the HUD and menus are, against paper white.": "Pegen skedus eo an HUD hag ar mennozhioù, a-enep gwenn ar paper.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Pegen pell e kendalc'h ar mobs, ar c'hoadoù hag ar mekanikoù da labourat. Amzer ar CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Pegen pell e vez tennet ar mobs hag an traoù, evel ul lodenn eus ar pezh a vez graet normal.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Tremen a ra an douaroù kuzhet a-dreñv rannoù serr. Koustañ a ra kalz.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Araokaet",
|
||||
"Undo": "Dizober",
|
||||
"Search options": "Dibarzhioù klask",
|
||||
"Shortcut": "Berradennoù",
|
||||
"Distance": "Pellder",
|
||||
"Display": "Diskouez",
|
||||
"Interface": "Etrefas",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibrañ...",
|
||||
"Calibrate Anyway...": "Kalibrañ koulskoude...",
|
||||
"Use Automatic Setup": "Implijout arventennoù emgefre",
|
||||
"Shortcut: %s": "Berradennoù : %s",
|
||||
"Next": "Da heul",
|
||||
"HDR Calibration %s/%s: %s": "Kalibradur HDR %s/%s : %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Lakaat a ra an tri skramm leun a-is, ur skeudenn amprouiñ bep tro.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Un alc'hwez a zigor ar skramm-mañ eus ar c'hoari. N'eo ket stag da gentañ.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "N'eo ket bet embannet gant ho skramm pegen sklaer e teu da vezañ : kalibret evit e lakaat war-sav.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Kefluniet dija evit ho skramm. Kalibret nemet ma seblant HDR bezañ fazius.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Lakaat a ra ar sked uhelañ hag ar gwenn paper en-dro e kefluniadur ho skramm.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Podiže sjene do najcrnje crne vašeg ekrana. 0: prava crna, bez podizanja.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Kako svetli naglasci postaju. Automatski: vrhunac o kojem vaš sistem prijavljuje.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Koliko svijetlo izgleda bijelo u svijetu. Automatski: bijela vaše radne površine.",
|
||||
"How bright the HUD and menus are, against paper white.": "Koliko su svijetli HUD i meniji, naspram bijelog papira.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Koliko mobovi, usjevi i mašine rade. CPU vrijeme.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Koliko su udaljeni mobovi i predmeti, kao udio normalnog.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Preskače teren skriven iza zatvorenih dijelova. Isključenje košta puno.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Napredno",
|
||||
"Undo": "Poništi",
|
||||
"Search options": "Opcije pretraživanja",
|
||||
"Shortcut": "Prečica",
|
||||
"Distance": "Udaljenost",
|
||||
"Display": "Ekran",
|
||||
"Interface": "Interfejs",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibriraj...",
|
||||
"Calibrate Anyway...": "Kalibriraj svejedno...",
|
||||
"Use Automatic Setup": "Koristite automatsko podešavanje",
|
||||
"Shortcut: %s": "Prečica: %s",
|
||||
"Next": "Sledeći",
|
||||
"HDR Calibration %s/%s: %s": "HDR kalibracija %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Postavlja tri ispod preko celog ekrana, jednu po jednu probnu sliku.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Taster koji otvara ovaj ekran iz igre. U početku nije vezan.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Vaš displej nije rekao koliko svetli: kalibrirajte da biste ga postavili.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Već postavljeno za vaš ekran. Kalibrirajte samo ako HDR izgleda pogrešno.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Vraća Peak Brightness i Paper White u postavke vašeg ekrana.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Puja les ombres fins al negre més fosc de la teva pantalla. 0: negre pur, sense pujar.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Com es fan els reflexos brillants. Automàtic: el pic que informa el vostre sistema.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Com de brillant es veu el blanc al món. Automàtic: el blanc de l'escriptori.",
|
||||
"How bright the HUD and menus are, against paper white.": "Què brillants són l'HUD i els menús, contra el paper blanc.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Fins on segueixen treballant les turbes, els conreus i les màquines. Temps de CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "A quina distància es dibuixen les turbes i els articles, com a part de la normalitat.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Salta el terreny amagat darrere de seccions tancades. Off costa molt.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Avançat",
|
||||
"Undo": "Desfer",
|
||||
"Search options": "Opcions de cerca",
|
||||
"Shortcut": "Drecera",
|
||||
"Distance": "Distància",
|
||||
"Display": "Mostra",
|
||||
"Interface": "Interfície",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Calibrar...",
|
||||
"Calibrate Anyway...": "Calibra de totes maneres...",
|
||||
"Use Automatic Setup": "Utilitzeu la configuració automàtica",
|
||||
"Shortcut: %s": "Drecera: %s",
|
||||
"Next": "A continuació",
|
||||
"HDR Calibration %s/%s: %s": "Calibració HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Estableix les tres imatges de sota de pantalla completa, una imatge de prova a la vegada.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Una clau que obre aquesta pantalla des del joc. No lligat al principi.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "La pantalla no va dir la brillantor que té: calibra per configurar-la.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Ja està configurat per a la vostra pantalla. Calibreu només si l'HDR sembla incorrecte.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Torna a posar la brillantor màxima i el blanc del paper a la configuració de la pantalla.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Zvedne stíny na nejtemnější černou vašeho displeje. 0: skutečná černá, bez zvednutí.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Jak se získá jasný melír. Auto: vrchol, který váš systém hlásí.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Jak jasně bílá ve světě vypadá. Auto: bílá vaší plochy.",
|
||||
"How bright the HUD and menus are, against paper white.": "Jak jasný je HUD a nabídky oproti bílé na papíře.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Jak dalece davy, plodiny a stroje fungují. CPU čas.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Jak daleko jsou mobové a předměty nakresleny jako podíl normálu.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Přeskočí terén skrytý za uzavřenými úseky. Vypnutí stojí hodně.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Pokročilé",
|
||||
"Undo": "Vrátit zpět",
|
||||
"Search options": "Možnosti vyhledávání",
|
||||
"Shortcut": "Zkratka",
|
||||
"Distance": "Vzdálenost",
|
||||
"Display": "Displej",
|
||||
"Interface": "Rozhraní",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibrovat...",
|
||||
"Calibrate Anyway...": "Přesto kalibrovat...",
|
||||
"Use Automatic Setup": "Použijte Automatické nastavení",
|
||||
"Shortcut: %s": "Zkratka: %s",
|
||||
"Next": "Další",
|
||||
"HDR Calibration %s/%s: %s": "Kalibrace HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Nastaví tři pod celou obrazovkou, vždy jeden testovací obrázek.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Klíč, který otevře tuto obrazovku ze hry. Zpočátku bez vazby.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Váš displej neříkal, jak jasný je: zkalibrujte jej, abyste jej nastavili.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Již nastaveno pro váš displej. Kalibrujte pouze v případě, že HDR vypadá špatně.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Vrátí maximální jas a papírovou bílou zpět do nastavení vašeho displeje.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Мӗлкесене дисплейӑн чи тӗттӗм хури ҫине ҫӗклет. 0: чӑн хура, ҫӗклевсӗр.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Мӗнле ҫутӑ ҫутӑсем пулаҫҫӗ. Авто: сирӗн системӑн пӗлтерекен пикӗ.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Тӗнчере шурӑ мӗнле ҫутӑ курӑнать. Авто: эсир рабочий столӑн шурри.",
|
||||
"How bright the HUD and menus are, against paper white.": "HUD тата менюсем мӗнле ҫутӑ, хут ҫинчи шурӑ тӗспе танлаштарсан.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Мобсем, культурӑсем тата машинӑсем мӗн таран ӗҫлеҫҫӗ. Процессор вӑхӑчӗ.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Мобсемпе япаласем мӗн чухлӗ аяккалла туртӑнаҫҫӗ, йӗркеллӗ пай пек.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Хупӑ участоксем хыҫӗнче пытаннӑ ҫӗре сиктерсе хӑварать. Офф нумай тӑкакланать.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Малалла",
|
||||
"Undo": "Каялла тавӑр",
|
||||
"Search options": "Шырав опцийӗсем",
|
||||
"Shortcut": "Кӗске ҫул",
|
||||
"Distance": "Инҫет",
|
||||
"Display": "Дисплей",
|
||||
"Interface": "Интерфейс",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Калибровка...",
|
||||
"Calibrate Anyway...": "Ҫапах та калибровка...",
|
||||
"Use Automatic Setup": "Автоматла настройкӑпа усӑ курӑр",
|
||||
"Shortcut: %s": "Кӗске ҫул: %s",
|
||||
"Next": "Малалла",
|
||||
"HDR Calibration %s/%s: %s": "HDR калибровка %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Аялта виҫҫӗшне тулли экран ҫине лартать, пӗрер тӗрӗслев ӳкерчӗкӗ.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Вӑйӑран ҫак экрана уҫакан уҫҫи. Малтанах ҫыхӑнман.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Сирӗн дисплей ҫинче вӑл мӗнле ҫутӑ пулнине каламан: ӑна лартма калибровка тумалла.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Сирӗн дисплей валли хатӗрленӗ ӗнтӗ. HDR тӗрӗс мар курӑнсан ҫеҫ калибровка тӑвӑр.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Чи пысӑк ҫутӑлӑха тата хут шуррине сирӗн дисплей настройкине каялла тавӑрать.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Yn codi cysgodion i ddu tywyllaf eich arddangosfa. 0: du go iawn, dim codi.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Sut mae uchafbwyntiau disglair yn ei gael. Auto: yr uchafbwynt y mae eich system yn ei adrodd.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Pa mor llachar y mae gwyn yn edrych yn y byd. Awtomatig: gwyn eich bwrdd gwaith.",
|
||||
"How bright the HUD and menus are, against paper white.": "Pa mor llachar yw'r HUD a'r bwydlenni, yn erbyn papur gwyn.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Pa mor bell y mae mobs, cnydau a pheiriannau yn dal i weithio. Amser CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Pa mor bell i ffwrdd mae mobs ac eitemau yn cael eu tynnu, fel cyfran o'r arferol.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Sgipiau tir wedi'i guddio y tu ôl i adrannau caeedig. Mae i ffwrdd yn costio llawer.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Uwch",
|
||||
"Undo": "Dadwneud",
|
||||
"Search options": "Dewisiadau chwilio",
|
||||
"Shortcut": "Llwybr byr",
|
||||
"Distance": "Pellter",
|
||||
"Display": "Arddangos",
|
||||
"Interface": "Rhyngwyneb",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Graddnodi...",
|
||||
"Calibrate Anyway...": "Calibro beth bynnag...",
|
||||
"Use Automatic Setup": "Defnyddiwch Gosodiad Awtomatig",
|
||||
"Shortcut: %s": "Llwybr byr: %s",
|
||||
"Next": "Nesaf",
|
||||
"HDR Calibration %s/%s: %s": "Graddnodi HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Yn gosod y tri isod sgrin lawn, un llun prawf ar y tro.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Allwedd sy'n agor y sgrin hon o'r gêm. Heb ei rwymo ar y dechrau.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Ni ddywedodd eich arddangosfa pa mor llachar y mae'n ei gael: graddnodwch i'w osod.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Eisoes wedi'i osod ar gyfer eich arddangosfa. Calibrowch dim ond os yw HDR yn edrych yn anghywir.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Yn rhoi Disgleirdeb Peak a Phapur Gwyn yn ôl i drefniant eich arddangosfa.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Løfter skygger op på skærmens mørkeste sort. 0: ægte sort, ingen løft.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Hvor lyse højdepunkter bliver. Auto: det højeste, dit system rapporterer.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Hvor lyst hvid ser ud i verden. Auto: din skrivebords hvide.",
|
||||
"How bright the HUD and menus are, against paper white.": "Hvor lys HUD og menuer er i forhold til hvidt papir.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Hvor langt mobs, afgrøder og maskiner bliver ved med at arbejde. CPU tid.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Hvor langt væk mobs og genstande trækkes, som en andel af normalen.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Springer over terræn skjult bag lukkede sektioner. Off koster meget.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Avanceret",
|
||||
"Undo": "Fortryd",
|
||||
"Search options": "Søgemuligheder",
|
||||
"Shortcut": "Genvej",
|
||||
"Distance": "Afstand",
|
||||
"Display": "Skærm",
|
||||
"Interface": "Grænseflade",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibrer...",
|
||||
"Calibrate Anyway...": "Kalibrer alligevel...",
|
||||
"Use Automatic Setup": "Brug automatisk opsætning",
|
||||
"Shortcut: %s": "Genvej: %s",
|
||||
"Next": "Næste",
|
||||
"HDR Calibration %s/%s: %s": "HDR-kalibrering %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Indstiller de tre nedenfor i fuld skærm, et testbillede ad gangen.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "En tast, der åbner denne skærm fra spillet. Ikke bundet i starten.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Din skærm sagde ikke, hvor lys den bliver: Kalibrer for at konfigurere den.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Allerede konfigureret til din skærm. Kalibrer kun, hvis HDR ser forkert ud.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Sætter Peak Brightness og Paper White tilbage til din skærms opsætning.",
|
||||
|
||||
@@ -290,7 +290,6 @@
|
||||
"Advanced": "Erweitert",
|
||||
"Undo": "Rückgängig",
|
||||
"Search options": "Einstellungen durchsuchen",
|
||||
"Shortcut": "Tastenkürzel",
|
||||
"Distance": "Entfernung",
|
||||
"Display": "Anzeige",
|
||||
"Interface": "Oberfläche",
|
||||
@@ -440,7 +439,6 @@
|
||||
"Sets the options below together. Changing one makes it Custom.": "Stellt Optionen darunter ein. Änderung = „Benutzerdefiniert“.",
|
||||
"Lava, fire and sunlight shine brighter than white. Needs an HDR display.": "Lava, Feuer, Sonne heller als Weiß. Braucht HDR-Bildschirm.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Wie hell Lichter werden. Auto: der Spitzenwert, den dein System meldet.",
|
||||
"How bright the HUD and menus are, against paper white.": "Wie hell HUD und Menüs im Vergleich zu Papierweiß sind.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Wie weit Kreaturen, Pflanzen und Maschinen weiterarbeiten. Kostet CPU-Zeit.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Zeichenweite für Kreaturen und Gegenstände, anteilig zur Norm.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Überspringt Gelände hinter geschlossenen Abschnitten. Aus kostet viel.",
|
||||
@@ -519,11 +517,9 @@
|
||||
"Calibrate...": "Kalibrieren …",
|
||||
"Calibrate Anyway...": "Trotzdem kalibrieren …",
|
||||
"Use Automatic Setup": "Automatische Einrichtung verwenden",
|
||||
"Shortcut: %s": "Tastenkürzel: %s",
|
||||
"Next": "Weiter",
|
||||
"HDR Calibration %s/%s: %s": "HDR-Kalibrierung %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Stellt die drei Werte darunter im Vollbild ein, jeweils mit einem Testbild.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Eine Taste, die diesen Bildschirm im Spiel öffnet. Zunächst nicht belegt.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Bildschirm meldete keine Helligkeit: zum Einrichten kalibrieren.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Bereits eingerichtet. Nur kalibrieren, wenn HDR falsch aussieht.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Stellt Spitzenhelligkeit und Papierweiß des Bildschirms wieder her.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Ανεβάζει τις σκιές στο πιο σκοτεινό μαύρο της οθόνης σας. 0: αληθινό μαύρο, χωρίς ανύψωση.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Πόσο φωτεινά σημεία αποκτούν. Auto: η κορύφωση που αναφέρει το σύστημά σας.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Πόσο φωτεινό φαίνεται το λευκό στον κόσμο. Αυτόματο: το λευκό της επιφάνειας εργασίας σας.",
|
||||
"How bright the HUD and menus are, against paper white.": "Πόσο φωτεινά είναι τα HUD και τα μενού, σε σχέση με το λευκό χαρτί.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Πόσο μακριά συνεχίζουν να λειτουργούν όχλοι, καλλιέργειες και μηχανές. Χρόνος CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Πόσο μακριά κληρώνονται όχλοι και αντικείμενα, ως ποσοστό του κανονικού.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Παρακάμπτει το έδαφος που κρύβεται πίσω από κλειστά τμήματα. Το off κοστίζει πολύ.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Προχωρημένο",
|
||||
"Undo": "Αναίρεση",
|
||||
"Search options": "Επιλογές αναζήτησης",
|
||||
"Shortcut": "Συντόμευση",
|
||||
"Distance": "Απόσταση",
|
||||
"Display": "Εμφάνιση",
|
||||
"Interface": "Διασύνδεση",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Βαθμονόμηση...",
|
||||
"Calibrate Anyway...": "Βαθμονόμηση πάντως...",
|
||||
"Use Automatic Setup": "Χρησιμοποιήστε την Αυτόματη Ρύθμιση",
|
||||
"Shortcut: %s": "Συντόμευση: %s",
|
||||
"Next": "Επόμενο",
|
||||
"HDR Calibration %s/%s: %s": "Βαθμονόμηση HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Ορίζει τις τρεις παρακάτω πλήρη οθόνη, μία δοκιμαστική εικόνα τη φορά.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Ένα κλειδί που ανοίγει αυτήν την οθόνη από το παιχνίδι. Δεν δεσμεύεται στην αρχή.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Η οθόνη σας δεν έλεγε πόσο φωτεινή γίνεται: βαθμονομήστε για να τη ρυθμίσετε.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Έχει ήδη ρυθμιστεί για την οθόνη σας. Βαθμονόμηση μόνο εάν το HDR φαίνεται λάθος.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Επαναφέρει το Peak Brightness και το Paper White στη ρύθμιση της οθόνης σας.",
|
||||
|
||||
@@ -310,7 +310,7 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Lifts shadows onto your display's darkest black. 0: true black, no lift.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "How bright highlights get. Auto: the peak your system reports.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "How bright white looks in the world. Auto: your desktop's white.",
|
||||
"How bright the HUD and menus are, against paper white.": "How bright the HUD and menus are, against paper white.",
|
||||
"How bright the HUD and menus are. Auto: at paper white.": "How bright the HUD and menus are. Auto: at paper white.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "How far mobs, crops and machines keep working. CPU time.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "How far away mobs and items are drawn, as a share of normal.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Skips terrain hidden behind closed sections. Off costs a lot.",
|
||||
@@ -367,7 +367,6 @@
|
||||
"Advanced": "Advanced",
|
||||
"Undo": "Undo",
|
||||
"Search options": "Search options",
|
||||
"Shortcut": "Shortcut",
|
||||
"Distance": "Distance",
|
||||
"Display": "Display",
|
||||
"Interface": "Interface",
|
||||
@@ -438,11 +437,9 @@
|
||||
"Calibrate...": "Calibrate...",
|
||||
"Calibrate Anyway...": "Calibrate Anyway...",
|
||||
"Use Automatic Setup": "Use Automatic Setup",
|
||||
"Shortcut: %s": "Shortcut: %s",
|
||||
"Next": "Next",
|
||||
"HDR Calibration %s/%s: %s": "HDR Calibration %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Sets the three below full screen, one test picture at a time.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "A key that opens this screen from the game. Not bound at first.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Your display didn't say how bright it gets: calibrate to set it up.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Already set up for your display. Only calibrate if HDR looks wrong.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Puts Peak Brightness and Paper White back to your display's setup.",
|
||||
@@ -1058,5 +1055,8 @@
|
||||
"horizon.studio.topbar.add_marker": "Add Marker",
|
||||
"horizon.studio.topbar.clear_keyframes": "🗑 Clear Keyframes",
|
||||
"horizon.studio.topbar.timeline_hud": "⏱ Timeline",
|
||||
"horizon.studio.topbar.split_scene": "Split Scene"
|
||||
"horizon.studio.topbar.split_scene": "Split Scene",
|
||||
"horizon.recipes.fuel.options": "Hold SHIFT to pin this tooltip, then click an ingredient to view recipes.",
|
||||
"horizon.recipes.fuel.any": "Any Fuel",
|
||||
"horizon.recipes.fuel.minecraft": "Minecraft"
|
||||
}
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Levas ombrojn al la plej malhela nigro de via ekrano. 0: vera nigro, sen levo.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Kiel brilaj brilaĵoj ricevas. Aŭtomata: la pinto kiun via sistemo raportas.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Kiom hela blanko aspektas en la mondo. Aŭtomate: la blanko de via labortablo.",
|
||||
"How bright the HUD and menus are, against paper white.": "Kiel brilaj la HUD kaj menuoj estas, kontraŭ papera blanka.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Kiom malproksime amasoj, kultivaĵoj kaj maŝinoj daŭre funkcias. CPU-tempo.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Kiom malproksime amasoj kaj eroj estas tiritaj, kiel parto de normalo.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Saltas terenon kaŝitan malantaŭ fermitaj sekcioj. For kostas multe.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Altnivela",
|
||||
"Undo": "Malfari",
|
||||
"Search options": "Serĉaj opcioj",
|
||||
"Shortcut": "Ŝparvojo",
|
||||
"Distance": "Distanco",
|
||||
"Display": "Montru",
|
||||
"Interface": "Interfaco",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibri...",
|
||||
"Calibrate Anyway...": "Kalibru ĉiuokaze...",
|
||||
"Use Automatic Setup": "Uzu Aŭtomatan Agordon",
|
||||
"Shortcut: %s": "Ŝparvojo: %s",
|
||||
"Next": "Poste",
|
||||
"HDR Calibration %s/%s: %s": "HDR-Kalibrado %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Agordas la tri sub plenan ekranon, unu testan bildon samtempe.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Ŝlosilo, kiu malfermas ĉi tiun ekranon de la ludo. Komence ne ligita.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Via ekrano ne diris kiom brilas ĝi fariĝas: kalibru por agordi ĝin.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Jam agordita por via ekrano. Nur kalibru se HDR aspektas malĝusta.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Remetas Pintan Brilon kaj Paperan Blankan al la agordo de via ekrano.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Eleva las sombras hasta el negro más oscuro de tu pantalla. 0: negro puro, sin elevación.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Cuánto brillan los reflejos. Automático: el pico que informa tu sistema.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Qué tan brillante se ve el blanco en el mundo. Automático: el blanco de tu escritorio.",
|
||||
"How bright the HUD and menus are, against paper white.": "Qué tan brillantes son el HUD y los menús respecto al blanco de papel.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Hasta dónde siguen funcionando mobs, cultivos y máquinas. Tiempo de CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "A qué distancia se dibujan mobs y objetos, como proporción de lo normal.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Omite el terreno oculto tras secciones cerradas. Desactivarlo cuesta mucho.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Avanzado",
|
||||
"Undo": "Deshacer",
|
||||
"Search options": "Buscar opciones",
|
||||
"Shortcut": "Atajo",
|
||||
"Distance": "Distancia",
|
||||
"Display": "Pantalla",
|
||||
"Interface": "Interfaz",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Calibrar...",
|
||||
"Calibrate Anyway...": "Calibrar de todos modos...",
|
||||
"Use Automatic Setup": "Usar la configuración automática",
|
||||
"Shortcut: %s": "Atajo: %s",
|
||||
"Next": "Siguiente",
|
||||
"HDR Calibration %s/%s: %s": "Calibración HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Configura las tres opciones siguientes a pantalla completa, con una imagen de prueba cada vez.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Una tecla que abre esta pantalla desde el juego. Sin asignar al principio.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Tu pantalla no indicó cuánto brilla: calíbrala para configurarla.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Ya está configurado para tu pantalla. Calibra solo si el HDR se ve mal.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Devuelve Brillo máximo y Blanco de papel a la configuración de tu pantalla.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Tõstab varjud ekraani tumedaima mustani. 0: tõeline must, ilma tõstmiseta.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Kui eredad esiletõstud saavad. Automaatne: tipp, millest süsteem teatab.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Kui hele valge maailmas paistab. Automaatne: sinu töölaua valge.",
|
||||
"How bright the HUD and menus are, against paper white.": "Kui eredad on HUD ja menüüd pabervalge taustal.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Kui kaugele mobid, põllukultuurid ja masinad töötavad. CPU aeg.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Kui kaugele mobid ja esemed tõmmatakse, kui osa normaalsest.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Jätab vahele suletud lõikude taha peidetud maastiku. Off maksab palju.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Täpsemalt",
|
||||
"Undo": "Võta tagasi",
|
||||
"Search options": "Otsinguvalikud",
|
||||
"Shortcut": "Otsetee",
|
||||
"Distance": "Kaugus",
|
||||
"Display": "Ekraan",
|
||||
"Interface": "Liides",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibreeri...",
|
||||
"Calibrate Anyway...": "Kalibreerige ikkagi...",
|
||||
"Use Automatic Setup": "Kasutage automaatset seadistust",
|
||||
"Shortcut: %s": "Otsetee: %s",
|
||||
"Next": "Edasi",
|
||||
"HDR Calibration %s/%s: %s": "HDR-kalibreerimine %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Määrab kolm allolevat täisekraani, üks testpilt korraga.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Klahv, mis avab mängust selle ekraani. Alguses ei köideta.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Teie ekraan ei öelnud, kui hele see muutub: seadistamiseks kalibreerige.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Teie kuva jaoks on juba seadistatud. Kalibreerige ainult siis, kui HDR tundub vale.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Tagab maksimaalse ereduse ja paberivalgeduse teie ekraani seadistustesse.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Itzalak zure pantailaren beltzik ilunenera igotzen ditu. 0: benetako beltza, igoerarik gabe.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Nola distiratsuak diren argiak. Auto: zure sistemak ematen duen gailurra.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Zenbat distiratzen duen zuriak munduan. Autoa: zure mahaigaineko zuria.",
|
||||
"How bright the HUD and menus are, against paper white.": "Zein distiratsuak diren HUD eta menuak, paper zuriaren aurka.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Noraino jarraitzen duten mafiak, laboreak eta makinak lanean. CPU denbora.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Noraino ateratzen diren mobs eta elementuak, normalaren zati gisa.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Sekzio itxien atzean ezkutatuta dagoen lurra saltatzen du. Off asko kostatzen da.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Aurreratua",
|
||||
"Undo": "Desegin",
|
||||
"Search options": "Bilaketa aukerak",
|
||||
"Shortcut": "Lasterbidea",
|
||||
"Distance": "Distantzia",
|
||||
"Display": "Bistaratzea",
|
||||
"Interface": "Interfazea",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibratu...",
|
||||
"Calibrate Anyway...": "Kalibratu Dena den...",
|
||||
"Use Automatic Setup": "Erabili konfigurazio automatikoa",
|
||||
"Shortcut: %s": "Lasterbidea: %s",
|
||||
"Next": "Hurrengoa",
|
||||
"HDR Calibration %s/%s: %s": "HDR Kalibrazioa %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Pantaila osoko azpian dauden hiru ezartzen ditu, probako argazki bat aldi berean.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Pantaila hau jokotik irekitzen duen giltza. Hasieran lotu gabe.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Pantailak ez du esan zenbat argi dagoen: kalibratu konfiguratzeko.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Dagoeneko konfiguratuta zaude zure pantailarako. Kalibratu HDR okerra bada bakarrik.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Distira gailurra eta Paper Zuria berriro jartzen ditu pantailaren konfiguraziora.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "سایهها را به تاریکترین سیاه نمایشگر شما میرساند. 0: سیاه واقعی، بدون بالا بردن.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "هایلایت ها چقدر روشن می شوند. خودکار: اوج گزارش سیستم شما.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "سفیدی در دنیا چقدر روشن دیده میشود. خودکار: سفیدی میزکار شما.",
|
||||
"How bright the HUD and menus are, against paper white.": "HUD و منوها در برابر سفید کاغذ چقدر روشن هستند.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "اوباش، محصولات زراعی و ماشینآلات تا کجا به کار خود ادامه میدهند. زمان CPU",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "اوباش و اقلام چقدر دور کشیده شده اند، به عنوان یک سهم عادی.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "از زمین های پنهان شده در پشت بخش های بسته می گذرد. هزینه های خاموش بسیار زیاد است.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "پیشرفته",
|
||||
"Undo": "واگرد",
|
||||
"Search options": "گزینه های جستجو",
|
||||
"Shortcut": "میانبر",
|
||||
"Distance": "فاصله",
|
||||
"Display": "نمایش",
|
||||
"Interface": "رابط",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "کالیبره کردن...",
|
||||
"Calibrate Anyway...": "به هر حال کالیبره کردن...",
|
||||
"Use Automatic Setup": "از تنظیم خودکار استفاده کنید",
|
||||
"Shortcut: %s": "میانبر: %s",
|
||||
"Next": "بعدی",
|
||||
"HDR Calibration %s/%s: %s": "کالیبراسیون HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "سه عکس زیر تمام صفحه را در یک زمان یک عکس آزمایشی تنظیم می کند.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "کلیدی که این صفحه را از بازی باز می کند. ابتدا مقید نیست.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "صفحه نمایش شما میزان روشنایی آن را بیان نکرده است: برای تنظیم آن کالیبره کنید.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "قبلاً برای نمایشگر شما تنظیم شده است. فقط در صورتی کالیبره کنید که HDR اشتباه به نظر برسد.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "حداکثر روشنایی و کاغذ سفید را به تنظیمات صفحه نمایش شما باز می گرداند.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Nostaa varjot näyttösi tummimpaan mustaan. 0: aito musta, ei nostoa.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Kuinka kirkkaat kohokohdat saavat. Auto: huippu, jonka järjestelmäsi raportoi.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Kuinka kirkkaalta valkoinen näyttää maailmassa. Automaattinen: työpöytäsi valkoinen.",
|
||||
"How bright the HUD and menus are, against paper white.": "Kuinka kirkkaita HUD ja valikot ovat paperinvalkoisia vastaan.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Kuinka pitkälle väkijoukot, viljat ja koneet toimivat. CPU-aika.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Kuinka kauas väkijoukot ja esineet piirretään, osuus normaalista.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Ohittaa suljettujen osien taakse piilotetun maaston. Poisto maksaa paljon.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Edistynyt",
|
||||
"Undo": "Kumoa",
|
||||
"Search options": "Hakuvaihtoehdot",
|
||||
"Shortcut": "Pikakuvake",
|
||||
"Distance": "Etäisyys",
|
||||
"Display": "Näyttö",
|
||||
"Interface": "Käyttöliittymä",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibroi...",
|
||||
"Calibrate Anyway...": "Kalibroi joka tapauksessa...",
|
||||
"Use Automatic Setup": "Käytä automaattista asetusta",
|
||||
"Shortcut: %s": "Pikanäppäin: %s",
|
||||
"Next": "Seuraavaksi",
|
||||
"HDR Calibration %s/%s: %s": "HDR-kalibrointi %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Asettaa kolme koko näytön alapuolelle yhden testikuvan kerrallaan.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Avain, joka avaa tämän näytön pelistä. Ei aluksi sidottu.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Näyttösi ei ilmoittanut, kuinka kirkkaaksi se tulee: kalibroi se määrittääksesi sen.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Näyttöäsi varten on jo määritetty. Kalibroi vain, jos HDR näyttää väärältä.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Palauttaa huippukirkkauden ja paperin valkoisen näytön asetuksiin.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Iniaangat ang mga anino sa pinakamadilim na itim ng iyong display. 0: totoong itim, walang angat.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Kung gaano kaliwanag ang mga highlight. Auto: ang pinakamataas na ulat ng iyong system.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Gaano kaliwanag ang puti sa mundo. Auto: ang puti ng iyong desktop.",
|
||||
"How bright the HUD and menus are, against paper white.": "Gaano kaliwanag ang HUD at mga menu, laban sa puting papel.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Hanggang saan patuloy na gumagana ang mga mandurumog, pananim at makina. oras ng CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Kung gaano kalayo ang mga mandurumog at mga item ay iginuhit, bilang bahagi ng normal.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Nilalaktawan ang lupain na nakatago sa likod ng mga saradong seksyon. Malaki ang gastos sa off.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Advanced",
|
||||
"Undo": "I-undo",
|
||||
"Search options": "Mga opsyon sa paghahanap",
|
||||
"Shortcut": "Shortcut",
|
||||
"Distance": "Distansya",
|
||||
"Display": "Pagpapakita",
|
||||
"Interface": "Interface",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "I-calibrate...",
|
||||
"Calibrate Anyway...": "Mag-calibrate pa rin...",
|
||||
"Use Automatic Setup": "Gamitin ang Awtomatikong Pag-setup",
|
||||
"Shortcut: %s": "Shortcut: %s",
|
||||
"Next": "Susunod",
|
||||
"HDR Calibration %s/%s: %s": "Pag-calibrate ng HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Itinatakda ang tatlo sa ibaba ng full screen, isang pagsubok na larawan sa isang pagkakataon.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Isang susi na nagbubukas ng screen na ito mula sa laro. Hindi nakatali sa una.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Hindi sinabi ng iyong display kung gaano ito kaliwanag: i-calibrate para i-set up ito.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Naka-set up na para sa iyong display. I-calibrate lang kung mukhang mali ang HDR.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Ibinabalik ang Peak Brightness at Paper White sa setup ng iyong display.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Lyftir skuggum upp á myrkasta svart á tínum skjá. 0: veruligt svart, ongin lyfting.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Hvussu bjart hæddarpunkt fáa. Sjálvvirkandi: toppurin, sum tín skipan greiðir frá.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Hvussu bjart hvítt sær út í heiminum. Sjálvvirkandi: hvítt á tínum skriviborði.",
|
||||
"How bright the HUD and menus are, against paper white.": "Hvussu ljós HUD og valmyndir eru, móti pappírshvítum.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Hvussu langt mobbar, grøðir og maskinur halda fram at virka. CPU tíð.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Hvussu langt burtur mobbar og lutir eru drignir, sum partur av vanligum.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Sleppur lendi goymt aftan fyri stongdar partar. Av kostar nógv.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Framkomin",
|
||||
"Undo": "Angra",
|
||||
"Search options": "Leitimøguleikar",
|
||||
"Shortcut": "Snarvegur",
|
||||
"Distance": "Fjarstøða",
|
||||
"Display": "Sýn",
|
||||
"Interface": "Grunnflata",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibrera...",
|
||||
"Calibrate Anyway...": "Kalibrera allíkavæl...",
|
||||
"Use Automatic Setup": "Brúka sjálvvirkandi uppseting",
|
||||
"Shortcut: %s": "Snarvegur: %s",
|
||||
"Next": "Næsta",
|
||||
"HDR Calibration %s/%s: %s": "HDR-kalibrering %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Setur tey trý niðanfyri fullan skerm, eina royndarmynd í senn.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Ein lykil, sum letur upp hendan skermin frá spælinum. Ikki bundin í fyrstuni.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Títt skjálvti segði ikki, hvussu ljóst tað blívur: kalibrera fyri at seta tað upp.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Longu sett upp til tín skjálvta. Kalibrera bert um HDR sær skeivt út.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Setur Toppljósstyrki og Pappírshvítt aftur til uppsetingina á skjánum.",
|
||||
|
||||
@@ -332,7 +332,6 @@
|
||||
"Sets the options below together. Changing one makes it Custom.": "Règle les options ci-dessous. Modifier une : « Personnalisé ».",
|
||||
"Lava, fire and sunlight shine brighter than white. Needs an HDR display.": "Lave, feu et soleil plus vifs que le blanc. Écran HDR requis.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "La luminosité des hautes lumières. Auto : le pic indiqué par votre système.",
|
||||
"How bright the HUD and menus are, against paper white.": "La luminosité du HUD et des menus, par rapport au blanc papier.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Portée d'activité des créatures, cultures, machines. Coût : CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Distance des créatures et objets, en part de la normale.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Ignore le terrain caché. Désactiver coûte cher.",
|
||||
@@ -407,11 +406,9 @@
|
||||
"Calibrate...": "Calibrer...",
|
||||
"Calibrate Anyway...": "Calibrer quand même...",
|
||||
"Use Automatic Setup": "Utiliser la configuration automatique",
|
||||
"Shortcut: %s": "Raccourci : %s",
|
||||
"Next": "Suivant",
|
||||
"HDR Calibration %s/%s: %s": "Calibrage HDR %s/%s : %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Règle les trois valeurs ci-dessous en plein écran, une image test à la fois.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Une touche qui ouvre cet écran depuis le jeu. Non assignée au départ.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Votre écran n'a pas indiqué sa luminosité : calibrez-le.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Déjà configuré. Calibrez seulement si le HDR semble incorrect.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Rétablit Luminosité max. et Point blanc de votre écran.",
|
||||
@@ -675,7 +672,6 @@
|
||||
"Advanced": "Avancé",
|
||||
"Undo": "Annuler",
|
||||
"Search options": "Rechercher des options",
|
||||
"Shortcut": "Raccourci",
|
||||
"Sky and weather": "Ciel et météo",
|
||||
"Lighting and entities": "Éclairage et entités",
|
||||
"Chunk loading": "Chargement des tronçons",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Al alce lis ombris sul neri plui scur dal to visôr. 0: neri vêr, cence alçâ.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Cuant che i ponts clârs a deventin luminosis. Auto: il massim dai segnalazions dal sisteme.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Cuant che al somee lûs il blanc tal mont. Automatic: il blanc dal to scritori.",
|
||||
"How bright the HUD and menus are, against paper white.": "Cuant che a son luminosis il HUD e i menus, cuintri dal blanc di cjarte.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Fin dulà che lis mobis, lis coltivazions e lis machinis a continuin a lavorâ. Timp dal CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Cuant lontan che a son tirâts fûr lis mobis e i ogjets, come part dal normâl.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Salte il teren scuindût daûr di sezions sieradis. Off al coste une vore.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Avanzade",
|
||||
"Undo": "Annulâ",
|
||||
"Search options": "Opzions di ricercje",
|
||||
"Shortcut": "Scurtis",
|
||||
"Distance": "Distance",
|
||||
"Display": "Visualizazion",
|
||||
"Interface": "Interface",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Calibrâ...",
|
||||
"Calibrate Anyway...": "Calibrâ in ogni câs...",
|
||||
"Use Automatic Setup": "Utilizâ la configurazion automatiche",
|
||||
"Shortcut: %s": "Scurtis: %s",
|
||||
"Next": "Sucessîf",
|
||||
"HDR Calibration %s/%s: %s": "Taradure HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Imposta i trê sot dal schermi intîr, une imagjin di prove par volte.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Une clâf che e vierç chest schermi dal zûc. No leât tal imprin.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Il display nol diseve cetant che al devente luminôs: calibrâlu par configurâlu.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Za configurât pal to display. Calibrâ dome se il HDR al somee sbaglât.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Al torne a meti la luminositât di massime e il blanc di cjarte inte configurazion dal display.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Tilt skaad op nei it tsjûkste swart fan jo display. 0: echt swart, gjin oplichting.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Hoe ljochte hichtepunten krije. Auto: de pyk dy't jo systeem rapportearret.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Hoe helder wyt yn 'e wrâld liket. Auto: it wyt fan jo buroblêd.",
|
||||
"How bright the HUD and menus are, against paper white.": "Hoe helder de HUD en menu's binne, tsjin papierwyt.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Hoe fier mobs, gewaaksen en masines bliuwe wurkjen. CPU tiid.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Hoe fier fuort mobs en items wurde lutsen, as in oandiel fan normale.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Skips terrein ferburgen efter sletten seksjes. Off kostet in soad.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Avansearre",
|
||||
"Undo": "Ungedien meitsje",
|
||||
"Search options": "Sykje opsjes",
|
||||
"Shortcut": "Fluchtoets",
|
||||
"Distance": "Ofstân",
|
||||
"Display": "Byldskerm",
|
||||
"Interface": "Ynterface",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibrearje...",
|
||||
"Calibrate Anyway...": "Kalibrearje dochs...",
|
||||
"Use Automatic Setup": "Brûk Automatyske opset",
|
||||
"Shortcut: %s": "Fluchtoets: %s",
|
||||
"Next": "Folgjende",
|
||||
"HDR Calibration %s/%s: %s": "HDR-kalibraasje %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Stelt de trije hjirûnder folslein skerm, ien testfoto tagelyk.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "In kaai dy't iepenet dit skerm út it spul. Earst net bûn.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Jo display sei net hoe helder it wurdt: kalibrearje om it yn te stellen.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Al ynsteld foar jo display. Kalibrearje allinich as HDR ferkeard sjocht.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Set Peak Brightness en Paper White werom nei de opset fan jo display.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Ardaíonn scáthanna go dtí an dubh is dorcha ar do thaispeántas. 0: fíordhubh, gan ardú.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Conas a fhaigheann buaicphointí geala. Auto: an bhuaic tuairiscí do chórais.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Cé chomh geal is a fheictear bán sa domhan. Uathoibríoch: bán do dheisce.",
|
||||
"How bright the HUD and menus are, against paper white.": "Cé chomh geal is atá an HUD agus na biachláir, i gcoinne bán páipéir.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Cé chomh fada agus a leanann mobs, barraí agus meaisíní ag obair. Am LAP.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Cé chomh fada uaidh a tharraingítear mobs agus míreanna, mar sciar den ghnáth.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Scipeanna tír-raon i bhfolach taobh thiar codanna dúnta. Lasmuigh costais go leor.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Casta",
|
||||
"Undo": "Cealaigh",
|
||||
"Search options": "Roghanna cuardaigh",
|
||||
"Shortcut": "aicearra",
|
||||
"Distance": "Fad",
|
||||
"Display": "Taispeáint",
|
||||
"Interface": "Comhéadan",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Calabraigh...",
|
||||
"Calibrate Anyway...": "Calabraigh Ar aon nós...",
|
||||
"Use Automatic Setup": "Úsáid Socrú Uathoibríoch",
|
||||
"Shortcut: %s": "Aicearra: %s",
|
||||
"Next": "Ar aghaidh",
|
||||
"HDR Calibration %s/%s: %s": "Calabrú HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Socraíonn sé na trí thíos scáileán iomlán, pictiúr tástála amháin ag an am.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Eochair a osclaíonn an scáileán seo ón gcluiche. Gan cheangal ar dtús.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Níor dúirt do thaispeántas cé chomh geal agus atá sé: calabraigh chun é a shocrú.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Socraithe cheana féin le haghaidh do thaispeántais. Ná calabraigh ach amháin má tá cuma mícheart ar HDR.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Cuireann Buaic Ghile agus Páipéar Bán ar ais go dtí socrú do thaispeántais.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "A' togail fhaileasan gu dubh as dorcha an taisbeanaidh agad. 0: fìor dhubh, gun togail.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Mar a gheibh seallaidhean soilleir. Auto: an ìre as àirde a tha an siostam agad ag aithris.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Dè cho soilleir 's a tha geal a' coimhead san t-saoghal. Auto: geal an deasga agad.",
|
||||
"How bright the HUD and menus are, against paper white.": "Dè cho soilleir sa tha an HUD agus na clàran-bìdh, an aghaidh pàipear geal.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Dè cho fada ‘s a chumas mobs, bàrr agus innealan ag obair. Uair CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Dè cho fada air falbh tha mobs agus nithean air an tarraing, mar chuibhreann den àbhaist.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Sgiobaidhean talmhainn falaichte air cùl earrannan dùinte. Cosgaidh dheth tòrr.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Adhartach",
|
||||
"Undo": "Neo-dhèanamh",
|
||||
"Search options": "Rannsaich roghainnean",
|
||||
"Shortcut": "Ath-ghoirid",
|
||||
"Distance": "Astar",
|
||||
"Display": "Taisbeanadh",
|
||||
"Interface": "Eadar-aghaidh",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Calibraich...",
|
||||
"Calibrate Anyway...": "Calibrate co-dhiù...",
|
||||
"Use Automatic Setup": "Cleachd suidheachadh fèin-ghluasadach",
|
||||
"Shortcut: %s": "Ath-ghoirid: %s",
|
||||
"Next": "Air adhart",
|
||||
"HDR Calibration %s/%s: %s": "Calibration HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Suidhich na trì gu h-ìosal làn-sgrìn, aon dealbh deuchainn aig aon àm.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Iuchair a dh'fhosglas an sgrìn seo bhon gheama. Gun a bhith ceangailte an toiseach.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Cha d’ thuirt an taisbeanadh agad cho soilleir ‘s a gheibh e: calibrate gus a rèiteachadh.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Air a chuir air dòigh mu thràth airson do thaisbeanadh. Na dèan calibration ach ma tha HDR a’ coimhead ceàrr.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "A’ cur Peak Brightness agus Paper White air ais gu suidheachadh an taisbeanaidh agad.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Eleva as sombras ata o negro máis escuro da túa pantalla. 0: negro puro, sen elevación.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Como se fan os reflejos brillantes. Automático: o pico que informa o seu sistema.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Que brillante se ve o branco no mundo. Automático: o branco do teu escritorio.",
|
||||
"How bright the HUD and menus are, against paper white.": "Que brillantes son o HUD e os menús, contra o branco do papel.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Ata onde seguen traballando as turbas, os cultivos e as máquinas. Tempo de CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "A que distancia se debuxan as turbas e os elementos, como parte do normal.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Salta o terreo escondido detrás de seccións pechadas. Off custa moito.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Avanzado",
|
||||
"Undo": "Desfacer",
|
||||
"Search options": "Opcións de busca",
|
||||
"Shortcut": "Atallo",
|
||||
"Distance": "Distancia",
|
||||
"Display": "Mostrar",
|
||||
"Interface": "Interface",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Calibrar...",
|
||||
"Calibrate Anyway...": "Calibrar de todos os xeitos...",
|
||||
"Use Automatic Setup": "Use a configuración automática",
|
||||
"Shortcut: %s": "Atallo: %s",
|
||||
"Next": "A continuación",
|
||||
"HDR Calibration %s/%s: %s": "Calibración HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Establece os tres debaixo da pantalla completa, unha imaxe de proba á vez.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Unha tecla que abre esta pantalla desde o xogo. Non atado ao principio.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "A túa pantalla non indica o brillo que ten: calíbraa para configurala.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Xa estás configurado para a túa pantalla. Calibra só se o HDR parece incorrecto.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Devolve o brillo máximo e o branco de papel á configuración da pantalla.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Hāpai i nā aka i ka ʻeleʻele loa o kāu hōʻike. 0: ʻeleʻele maoli, ʻaʻohe hāpai.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Pehea e loaʻa ai nā hiʻohiʻona nani. Auto: ke kiʻekiʻe o kāu hōʻike pūnaewele.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Pehea ke keʻokeʻo o ka honua. Akomi: ke keʻokeʻo o kāu papa hana.",
|
||||
"How bright the HUD and menus are, against paper white.": "Pehea ka mālamalama o ka HUD a me nā menus, e kūʻē i ka pepa keʻokeʻo.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Pehea ka lōʻihi o ka hana ʻana o nā kānaka, nā mea kanu a me nā mīkini. manawa CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Pehea ka lōʻihi o ka huki ʻia ʻana o nā poʻe pōʻino a me nā mea, ma ke ʻano he mea maʻamau.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Holo i ka ʻāina huna ma hope o nā ʻāpana pani. He nui ke kumu kūʻai.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Kiʻekiʻe",
|
||||
"Undo": "Wehe",
|
||||
"Search options": "Nā koho huli",
|
||||
"Shortcut": "Pōkole",
|
||||
"Distance": "mamao",
|
||||
"Display": "Hōʻike",
|
||||
"Interface": "Ikepili",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Hoʻoponopono ʻia...",
|
||||
"Calibrate Anyway...": "E hoʻokaʻawale i kēlā me kēia...",
|
||||
"Use Automatic Setup": "E hoʻohana i ka hoʻonohonoho ʻakomi",
|
||||
"Shortcut: %s": "Pōkole: %s",
|
||||
"Next": "Aʻe",
|
||||
"HDR Calibration %s/%s: %s": "Hoʻoponopono HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Hoʻonohonoho i nā ʻekolu ma lalo o ka pale piha, hoʻokahi kiʻi hoʻāʻo i ka manawa.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "He kī e wehe ana i kēia pale mai ka pāʻani. ʻAʻole paʻa i ka wā mua.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "ʻAʻole i haʻi mai kāu hōʻike i ke ʻano o kona ʻālohilohi: calibrate e hoʻonohonoho iā ia.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Ua hoʻonohonoho ʻia no kāu hōʻike. Hoʻopili wale inā ʻike hewa ka HDR.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Hoʻihoʻi i ka Peak Brightness a me ka Pepa Keʻokeʻo i ka hoʻonohonoho o kāu hōʻike.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "מרים צללים אל השחור הכהה ביותר של הצג שלך. 0: שחור אמיתי, ללא הרמה.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "כמה מדגישים בהירים מקבלים. אוטומטי: השיא שהמערכת שלך מדווחת עליו.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "כמה בהיר נראה לבן בעולם. אוטומטי: הלבן של שולחן העבודה שלך.",
|
||||
"How bright the HUD and menus are, against paper white.": "כמה בהירים ה-HUD והתפריטים, מול נייר לבן.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "עד כמה המון, יבולים ומכונות ממשיכים לעבוד. זמן מעבד.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "כמה רחוק נמשכים אספסוף ופריטים, כחלק מהרגיל.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "מדלג על שטח מוסתר מאחורי קטעים סגורים. חופש עולה הרבה.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "מתקדם",
|
||||
"Undo": "בטל",
|
||||
"Search options": "אפשרויות חיפוש",
|
||||
"Shortcut": "קיצור דרך",
|
||||
"Distance": "מרחק",
|
||||
"Display": "תצוגה",
|
||||
"Interface": "ממשק",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "כיול...",
|
||||
"Calibrate Anyway...": "כייל בכל מקרה...",
|
||||
"Use Automatic Setup": "השתמש בהגדרה אוטומטית",
|
||||
"Shortcut: %s": "קיצור דרך: %s",
|
||||
"Next": "הבא",
|
||||
"HDR Calibration %s/%s: %s": "כיול HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "מגדיר את שלושת המסך המלא מתחת, תמונת בדיקה אחת בכל פעם.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "מפתח שפותח את המסך הזה מהמשחק. לא קשור בהתחלה.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "הצג שלך לא אמר כמה הוא בהיר: כייל כדי להגדיר אותו.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "כבר מוגדר לתצוגה שלך. כייל רק אם HDR נראה שגוי.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "מחזיר את Peak Brightness ואת נייר לבן להגדרות התצוגה.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "परछाइयों को आपके डिस्प्ले के सबसे गहरे काले तक उठाता है। 0: शुद्ध काला, कोई उठाव नहीं।",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "हाइटलाइट्स कितने चमकीले होते हैं। ऑटो: आपका सिस्टम जो शिखर रिपोर्ट करता है।",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "दुनिया में सफेद कितना चमकीला दिखता है। ऑटो: आपके डेस्कटॉप का सफेद।",
|
||||
"How bright the HUD and menus are, against paper white.": "पेपर व्हाइट की तुलना में HUD और मेनू कितने चमकीले हैं।",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "मॉब्स, फसलें और मशीनें कितनी दूर तक काम करती रहती हैं। CPU समय।",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "सामान्य के हिस्से के रूप में, मॉब्स और आइटम कितनी दूर खींचे जाते हैं।",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "बंद खंडों के पीछे छिपा भू-भाग छोड़ देता है। बंद करने पर अधिक लागत आती है।",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "उन्नत",
|
||||
"Undo": "पूर्ववत करें",
|
||||
"Search options": "विकल्प खोजें",
|
||||
"Shortcut": "शॉर्टकट",
|
||||
"Distance": "दूरी",
|
||||
"Display": "डिस्प्ले",
|
||||
"Interface": "इंटरफ़ेस",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "कैलिब्रेट करें...",
|
||||
"Calibrate Anyway...": "वैसे भी कैलिब्रेट करें...",
|
||||
"Use Automatic Setup": "स्वचालित सेटअप का उपयोग करें",
|
||||
"Shortcut: %s": "शॉर्टकट: %s",
|
||||
"Next": "अगला",
|
||||
"HDR Calibration %s/%s: %s": "HDR कैलिब्रेशन %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "एक समय में एक परीक्षण चित्र के साथ, नीचे दिए गए तीनों को पूर्ण स्क्रीन पर सेट करता है।",
|
||||
"A key that opens this screen from the game. Not bound at first.": "एक कुंजी जो गेम से इस स्क्रीन को खोलती है। पहले से बाउंड नहीं है।",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "आपके डिस्प्ले ने यह नहीं बताया कि यह कितना चमकीला होता है: इसे सेट अप करने के लिए कैलिब्रेट करें।",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "आपके डिस्प्ले के लिए पहले से सेट अप है। केवल तभी कैलिब्रेट करें जब HDR गलत लगे।",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "पीक ब्राइटनेस और पेपर व्हाइट को आपके डिस्प्ले के सेटअप पर वापस रखता है।",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Podiže sjene do najtamnije crne vašeg zaslona. 0: prava crna, bez podizanja.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Koliko svijetli postaju svijetli dijelovi. Automatski: vršna vrijednost koju prijavljuje vaš sustav.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Koliko bijela izgleda svijetlo u svijetu. Automatski: bijela vaše radne površine.",
|
||||
"How bright the HUD and menus are, against paper white.": "Koliko su svijetli HUD i izbornici u odnosu na papirnato bijelu.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Koliko daleko čudovišta, usjevi i strojevi nastavljaju raditi. Vrijeme CPU-a.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Koliko se daleko crtaju čudovišta i predmeti, kao udio normalnog.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Preskače teren skriven iza zatvorenih dijelova. Isključeno opterećuje sustav.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Napredno",
|
||||
"Undo": "Poništi",
|
||||
"Search options": "Opcije pretraživanja",
|
||||
"Shortcut": "Prečac",
|
||||
"Distance": "Udaljenost",
|
||||
"Display": "Zaslon",
|
||||
"Interface": "Sučelje",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibriraj...",
|
||||
"Calibrate Anyway...": "Svejedno kalibriraj...",
|
||||
"Use Automatic Setup": "Koristi automatsku postavu",
|
||||
"Shortcut: %s": "Prečac: %s",
|
||||
"Next": "Sljedeće",
|
||||
"HDR Calibration %s/%s: %s": "HDR kalibracija %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Postavlja tri donja na cijeli zaslon, jednu testnu sliku po jednu.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Tipka koja otvara ovaj zaslon iz igre. U početku nije povezana.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Vaš zaslon nije javio koliko svijetli: kalibrirajte ga za postavljanje.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Već postavljeno za vaš zaslon. Kalibrirajte samo ako HDR izgleda pogrešno.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Vraća najveću svjetlinu i papirnato bijelu na postavke vašeg zaslona.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Az árnyékokat a kijelző legmélyebb feketéjére emeli. 0: valódi fekete, emelés nélkül.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Milyen fényesek a csúcsfények. Automatikus: a rendszer által jelentett csúcs.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Milyen fényesnek tűnik a fehér a világban. Automatikus: az asztal fehérje.",
|
||||
"How bright the HUD and menus are, against paper white.": "Milyen fényesek a HUD és a menük papírfehérrel szemben.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Meddig dolgoznak a csőcselék, a termények és a gépek. CPU idő.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Milyen messzire húzódnak a mobok és tárgyak, a normál arányaként.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Kihagyja a zárt szakaszok mögé rejtett terepet. Az off sokba kerül.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Haladó",
|
||||
"Undo": "Visszavonás",
|
||||
"Search options": "Keresési lehetőségek",
|
||||
"Shortcut": "Parancsikon",
|
||||
"Distance": "Távolság",
|
||||
"Display": "Kijelző",
|
||||
"Interface": "Interfész",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibrálás...",
|
||||
"Calibrate Anyway...": "Mindenesetre kalibráld...",
|
||||
"Use Automatic Setup": "Használja az Automatikus beállítást",
|
||||
"Shortcut: %s": "Parancsikon: %s",
|
||||
"Next": "Következő",
|
||||
"HDR Calibration %s/%s: %s": "HDR kalibrálás %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "A három alatti teljes képernyőt állítja be, egyszerre egy tesztképet.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Kulcs, amely megnyitja ezt a képernyőt a játékból. Először nem kötve.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "A kijelzője nem jelezte, hogy mennyire lesz fényes: kalibrálja a beállításhoz.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Már be van állítva a kijelzőjéhez. Csak akkor kalibráljon, ha a HDR rossznak tűnik.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Visszaállítja a csúcsfényerőt és a papírfehéret a kijelző beállításához.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Ստվերները բարձրացնում է ձեր էկրանի ամենամուգ սևին։ 0՝ իրական սև, առանց բարձրացման։",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Որքան վառ ընդգծումներ են ստանում: Ավտոմատ. ձեր համակարգի գագաթնակետը հաղորդում է:",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Թե որքան պայծառ է սպիտակը երևում աշխարհում։ Ավտոմատ՝ ձեր աշխատասեղանի սպիտակը։",
|
||||
"How bright the HUD and menus are, against paper white.": "Որքան վառ են HUD-ն ու մենյուները՝ թղթի սպիտակի դեմ:",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Որքան հեռու են աշխատում ամբոխները, մշակաբույսերը և մեքենաները: Պրոցեսորի ժամանակ.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Որքա՜ն հեռու են քաշված ամբոխներն ու իրերը՝ որպես նորմալի մասնաբաժին։",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Բաց է թողնում փակ հատվածների հետևում թաքնված տեղանքը: Off ծախսերը շատ.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Ընդլայնված",
|
||||
"Undo": "Հետարկել",
|
||||
"Search options": "Որոնման ընտրանքներ",
|
||||
"Shortcut": "Դյուրանցում",
|
||||
"Distance": "Հեռավորությունը",
|
||||
"Display": "Ցուցադրել",
|
||||
"Interface": "Ինտերֆեյս",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Կալիբրացիա...",
|
||||
"Calibrate Anyway...": "Կալիբրացիա, այնուամենայնիվ...",
|
||||
"Use Automatic Setup": "Օգտագործեք ավտոմատ կարգավորում",
|
||||
"Shortcut: %s": "Դյուրանցում՝ %s",
|
||||
"Next": "Հաջորդը",
|
||||
"HDR Calibration %s/%s: %s": "HDR չափորոշում %s/%s՝ %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Սահմանում է ներքևում գտնվող երեքը լիաէկրան, միաժամանակ մեկ փորձնական նկար:",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Բանալին, որը բացում է այս էկրանը խաղից: Սկզբում կապված չէ:",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Ձեր էկրանը չի ասում, թե որքան պայծառ է այն դառնում. չափաբերեք այն կարգավորելու համար:",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Արդեն ստեղծվել է ձեր ցուցադրման համար: Չափորոշեք միայն այն դեպքում, եթե HDR-ն սխալ տեսք ունի:",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Վերադարձնում է առավելագույն պայծառությունն ու թղթի սպիտակը ձեր էկրանի կարգավորումներին:",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Mengangkat bayangan ke hitam tergelap layar Anda. 0: hitam sejati, tanpa pengangkatan.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Seberapa terang sorotan cahaya. Otomatis: puncak yang dilaporkan oleh sistem Anda.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Seberapa terang warna putih di dunia. Otomatis: putih desktop Anda.",
|
||||
"How bright the HUD and menus are, against paper white.": "Seberapa terang HUD dan menu dibandingkan dengan putih kertas.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Seberapa jauh mob, tanaman, dan mesin tetap bekerja. Waktu CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Seberapa jauh mob dan item digambar, sebagai persentase dari normal.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Lewati medan yang tersembunyi di balik bagian tertutup. Nonaktif memakan banyak sumber daya.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Lanjutan",
|
||||
"Undo": "Urungkan",
|
||||
"Search options": "Cari opsi",
|
||||
"Shortcut": "Pintasan",
|
||||
"Distance": "Jarak",
|
||||
"Display": "Tampilan",
|
||||
"Interface": "Antarmuka",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kalibrasi...",
|
||||
"Calibrate Anyway...": "Tetap Kalibrasi...",
|
||||
"Use Automatic Setup": "Gunakan Pengaturan Otomatis",
|
||||
"Shortcut: %s": "Pintasan: %s",
|
||||
"Next": "Berikutnya",
|
||||
"HDR Calibration %s/%s: %s": "Kalibrasi HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Mengatur ketiga hal di bawah ini ke mode layar penuh, satu gambar uji dalam satu waktu.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Tombol untuk membuka layar ini dari dalam game. Belum diatur sebelumnya.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Layar Anda tidak melaporkan tingkat kecerahannya: lakukan kalibrasi untuk mengaturnya.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Sudah diatur untuk layar Anda. Kalibrasi ulang hanya jika tampilan HDR terlihat keliru.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Mengembalikan Kecerahan Puncak dan Putih Kertas ke pengaturan awal layar Anda.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Na-ebuli onyinyo ruo n'ojii kacha njọ nke ihuenyo gị. 0: ojii zuru oke, enweghị ebuli.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Kedu ka isi ihe na-egbuke egbuke si enweta. Akpaaka: ọnụ ọgụgụ kasị elu nke sistemụ gị na-akọ.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Otú ọcha si acha na ụwa. Akpaaka: ọcha nke desktọp gị.",
|
||||
"How bright the HUD and menus are, against paper white.": "Lee ka HUD na menus si na-enwu, megide ọcha akwụkwọ.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Ogologo oge ole na-eme mkpọtụ, ihe ọkụkụ na igwe na-arụ ọrụ. CPU oge.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Kedu ebe a na-adọta mobs na ihe dị anya, dịka òkè nke nkịtị.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Na-amafe ala zoro ezo n'azụ ngalaba mechiri emechi. Gbanyụọ na-efu nnukwu ego.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Nke dị elu",
|
||||
"Undo": "Megharịa",
|
||||
"Search options": "Chọọ nhọrọ",
|
||||
"Shortcut": "Ụzọ mkpirisi",
|
||||
"Distance": "Anya",
|
||||
"Display": "Ngosipụta",
|
||||
"Interface": "Nhazi ihu",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Hazie...",
|
||||
"Calibrate Anyway...": "Hazie agbanyeghị...",
|
||||
"Use Automatic Setup": "Jiri Ntọala akpaaka",
|
||||
"Shortcut: %s": "Ụzọ mkpirisi: %s",
|
||||
"Next": "Na-esote",
|
||||
"HDR Calibration %s/%s: %s": "HDR calibration %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Tọọ atọ n'okpuru ihuenyo zuru oke, otu foto nnwale n'otu oge.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Igodo na-emepe ihuenyo a site na egwuregwu. Ekebeghị ya na mbụ.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Ngosipụta gị ekwughị ka ọ na-egbuke egbuke: hazie ka ịtọlite ya.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Ahaziri maka ngosi gị. Naanị hazie ma ọ bụrụ na HDR adịghị mma.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Na-eweghachi Peak Brightness na White Akwụkwọ na ntọlite ihe ngosi gị.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Lyftir skuggum upp að dökkasta svarti skjásins. 0: ekta svart, engin lyfting.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Hversu bjartir hápunktar verða. Sjálfvirkt: hámarkið sem kerfið þitt tilkynnir.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Hversu bjart hvítt lítur út í heiminum. Sjálfvirk: hvítt skjáborðsins þíns.",
|
||||
"How bright the HUD and menus are, against paper white.": "Hversu björt HUD og valmyndir eru, á móti pappírshvítum.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Hversu langt múgur, uppskera og vélar halda áfram að vinna. CPU tími.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Hversu langt í burtu múgur og hlutir eru dregnir, sem hlutfall af venjulegum.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Sleppir landslagi sem er falið á bak við lokaða kafla. Off kostar mikið.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Ítarlegri",
|
||||
"Undo": "Afturkalla",
|
||||
"Search options": "Leitarmöguleikar",
|
||||
"Shortcut": "Flýtileið",
|
||||
"Distance": "Fjarlægð",
|
||||
"Display": "Skjár",
|
||||
"Interface": "Viðmót",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Kvarða...",
|
||||
"Calibrate Anyway...": "Kvörðuðu samt...",
|
||||
"Use Automatic Setup": "Notaðu sjálfvirka uppsetningu",
|
||||
"Shortcut: %s": "Flýtileið: %s",
|
||||
"Next": "Næst",
|
||||
"HDR Calibration %s/%s: %s": "HDR kvörðun %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Stillir þrjár fyrir neðan allan skjáinn, eina prufumynd í einu.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Lykill sem opnar þennan skjá úr leiknum. Ekki bundið í fyrstu.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Skjárinn þinn sagði ekki hversu bjartur hann verður: kvarðaðu til að setja hann upp.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Nú þegar sett upp fyrir skjáinn þinn. Kvörðaðu aðeins ef HDR lítur rangt út.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Setur Peak Brightness og Paper White aftur í uppsetningu skjásins þíns.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Solleva le ombre fino al nero più cupo del tuo schermo. 0: nero reale, nessun sollevamento.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Come diventano brillanti le luci. Auto: il picco segnalato dal sistema.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Quanto luminoso appare il bianco nel mondo. Auto: il bianco del tuo desktop.",
|
||||
"How bright the HUD and menus are, against paper white.": "Quanto sono luminosi l'HUD e i menu, rispetto al bianco della carta.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Fino a che punto mob, raccolti e macchine continuano a funzionare. Tempo della CPU.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Quanto lontano vengono disegnati mob e oggetti, come percentuale del normale.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Salta il terreno nascosto dietro le sezioni chiuse. Spendere costa molto.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Avanzato",
|
||||
"Undo": "Annulla",
|
||||
"Search options": "Opzioni di ricerca",
|
||||
"Shortcut": "Scorciatoia",
|
||||
"Distance": "Distanza",
|
||||
"Display": "Visualizzazione",
|
||||
"Interface": "Interfaccia",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Calibra...",
|
||||
"Calibrate Anyway...": "Calibra comunque...",
|
||||
"Use Automatic Setup": "Utilizza l'impostazione automatica",
|
||||
"Shortcut: %s": "Scorciatoia: %s",
|
||||
"Next": "Avanti",
|
||||
"HDR Calibration %s/%s: %s": "Calibrazione HDR %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Imposta le tre immagini sottostanti a schermo intero, un'immagine di prova alla volta.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Una chiave che apre questa schermata del gioco. All'inizio non legato.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Il display non ha indicato la luminosità: calibralo per configurarlo.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Già predisposto per il tuo display. Calibrare solo se l'HDR sembra sbagliato.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Riporta la luminosità di picco e il bianco della carta alla configurazione del display.",
|
||||
|
||||
@@ -315,7 +315,6 @@
|
||||
"Sets the options below together. Changing one makes it Custom.": "以下のオプションをまとめて設定します。どれかを変更するとカスタムになります。",
|
||||
"Lava, fire and sunlight shine brighter than white. Needs an HDR display.": "溶岩、火、太陽光は白よりも明るく輝きます。 HDRディスプレイが必要です。",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "ハイライトがどれだけ明るくなるか。自動: システムが報告するピーク。",
|
||||
"How bright the HUD and menus are, against paper white.": "紙の白に対する HUD とメニューの明るさ。",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "暴徒、作物、機械がどこまで機能し続けるか。 CPU時間。",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "通常の割合として、Mob とアイテムが描画される距離。",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "閉じたセクションの後ろに隠れている地形をスキップします。オフには多額の費用がかかります。",
|
||||
@@ -368,7 +367,6 @@
|
||||
"Advanced": "上級者向け",
|
||||
"Undo": "元に戻す",
|
||||
"Search options": "検索オプション",
|
||||
"Shortcut": "ショートカット",
|
||||
"Distance": "距離",
|
||||
"Display": "ディスプレイ",
|
||||
"Interface": "インターフェース",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "校正...",
|
||||
"Calibrate Anyway...": "とにかく校正してください...",
|
||||
"Use Automatic Setup": "自動セットアップを使用する",
|
||||
"Shortcut: %s": "ショートカット: %s",
|
||||
"Next": "次へ",
|
||||
"HDR Calibration %s/%s: %s": "HDR キャリブレーション %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "フルスクリーンの下の 3 つを、一度に 1 つのテスト画像を設定します。",
|
||||
"A key that opens this screen from the game. Not bound at first.": "ゲームからこの画面を開くキー。最初は縛られてない。",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "ディスプレイにはどのくらい明るくなるかは記載されていません。調整して設定してください。",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "ディスプレイ用にすでにセットアップされています。 HDR が間違っていると思われる場合にのみ調整してください。",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "ピークの明るさとペーパー ホワイトをディスプレイの設定に戻します。",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "ჩრდილებს ასწევს თქვენი ეკრანის ყველაზე ბნელ შავამდე. 0: ნამდვილი შავი, აწევის გარეშე.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "რამდენად ნათელი ხაზგასმა ხდება. ავტომატური: თქვენი სისტემის ანგარიშების პიკი.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "რამდენად ნათელია თეთრი სამყაროში. ავტო: თქვენი სამუშაო მაგიდის თეთრი.",
|
||||
"How bright the HUD and menus are, against paper white.": "რამდენად ნათელია HUD და მენიუები, ქაღალდის თეთრის წინააღმდეგ.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "რამდენად შორს მუშაობენ ბრბოები, ნათესები და მანქანები. CPU დრო.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "რამდენად შორს არის დახატული ბრბო და ნივთები, როგორც ნორმალური წილი.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "გამოტოვებს დახურულ მონაკვეთებს მიღმა დამალულ რელიეფს. გამორთვა ბევრი ღირს.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "გაფართოებული",
|
||||
"Undo": "გაუქმება",
|
||||
"Search options": "ძიების პარამეტრები",
|
||||
"Shortcut": "მალსახმობი",
|
||||
"Distance": "მანძილი",
|
||||
"Display": "ჩვენება",
|
||||
"Interface": "ინტერფეისი",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "დაკალიბრება...",
|
||||
"Calibrate Anyway...": "დაკალიბრება მაინც...",
|
||||
"Use Automatic Setup": "გამოიყენეთ ავტომატური დაყენება",
|
||||
"Shortcut: %s": "მალსახმობი: %s",
|
||||
"Next": "შემდეგი",
|
||||
"HDR Calibration %s/%s: %s": "HDR კალიბრაცია %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "აყენებს სრულ ეკრანზე ქვემოთ მოცემულ სამს, თითო სატესტო სურათს ერთდროულად.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "გასაღები, რომელიც ხსნის ამ ეკრანს თამაშიდან. თავდაპირველად არ არის შეკრული.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "თქვენს ეკრანს არ უთქვამს რამდენად ნათელი ხდება: დააკალიბრეთ მის დასაყენებლად.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "უკვე დაყენებულია თქვენი ეკრანისთვის. დაკალიბრება მხოლოდ იმ შემთხვევაში, თუ HDR არასწორად გამოიყურება.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "აბრუნებს მაქსიმალურ სიკაშკაშეს და ქაღალდის თეთრს თქვენი ეკრანის პარამეტრებში.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Көлеңкелерді дисплейіңіздің ең терең қарасына көтереді. 0: таза қара, көтерілусіз.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Жарқын нүктелер қаншалықты жарқын болады. Автоматты: жүйе есептерінің шыңы.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Әлемде ақ түстің қаншалықты жарық көрінетіні. Авто: жұмыс үстеліңіздің ақ түсі.",
|
||||
"How bright the HUD and menus are, against paper white.": "HUD және мәзірлер ақ қағазға қарағанда қаншалықты жарқын.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Топтар, дақылдар мен машиналар қаншалықты алыс жұмыс істейді. CPU уақыты.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Қалыпты үлес ретінде тобыр мен заттар қаншалықты алыс тартылады.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Жабық бөліктердің артына жасырылған жерді өткізіп жібереді. Өшіру көп шығынға ұшырайды.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Жетілдірілген",
|
||||
"Undo": "Болдырмау",
|
||||
"Search options": "Іздеу опциялары",
|
||||
"Shortcut": "Таңбаша",
|
||||
"Distance": "Қашықтық",
|
||||
"Display": "Дисплей",
|
||||
"Interface": "Интерфейс",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Калибрлеу...",
|
||||
"Calibrate Anyway...": "Қалай болғанда да калибрлеу...",
|
||||
"Use Automatic Setup": "Автоматты орнатуды пайдаланыңыз",
|
||||
"Shortcut: %s": "Таңбаша: %s",
|
||||
"Next": "Келесі",
|
||||
"HDR Calibration %s/%s: %s": "HDR калибрлеу %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Төмендегі үш толық экранды, бір уақытта бір сынақ суретін орнатады.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Ойыннан осы экранды ашатын перне. Басында байланысты емес.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Дисплей қаншалықты жарық болатынын айтпады: оны орнату үшін калибрленіңіз.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Дисплей үшін әлдеқашан орнатылған. HDR дұрыс емес болып көрінсе ғана калибрлендіріңіз.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Ең жоғары жарықтық пен ақ қағазды дисплей параметрлеріне қайтарады.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "ನೆರಳುಗಳನ್ನು ನಿಮ್ಮ ಡಿಸ್ಪ್ಲೇಯ ಕಪ್ಪು ಮಟ್ಟಕ್ಕೆ ಎತ್ತುತ್ತದೆ. 0: ನಿಜವಾದ ಕಪ್ಪು, ಎತ್ತುವಿಕೆ ಇಲ್ಲ.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "ಪ್ರಕಾಶಮಾನವಾದ ಮುಖ್ಯಾಂಶಗಳು ಹೇಗೆ ಸಿಗುತ್ತವೆ. ಸ್ವಯಂ: ನಿಮ್ಮ ಸಿಸ್ಟಂ ವರದಿಗಳ ಗರಿಷ್ಠ.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "ಜಗತ್ತಿನಲ್ಲಿ ಬಿಳಿ ಎಷ್ಟು ಪ್ರಕಾಶಮಾನವಾಗಿ ಕಾಣುತ್ತದೆ. ಆಟೋ: ನಿಮ್ಮ ಡೆಸ್ಕ್ಟಾಪ್ನ ಬಿಳಿ.",
|
||||
"How bright the HUD and menus are, against paper white.": "ಕಾಗದದ ಬಿಳಿಯ ವಿರುದ್ಧ HUD ಮತ್ತು ಮೆನುಗಳು ಎಷ್ಟು ಪ್ರಕಾಶಮಾನವಾಗಿವೆ.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "ಜನಸಮೂಹಗಳು, ಬೆಳೆಗಳು ಮತ್ತು ಯಂತ್ರಗಳು ಎಷ್ಟು ಕೆಲಸ ಮಾಡುತ್ತವೆ. CPU ಸಮಯ.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "ಜನಸಮೂಹ ಮತ್ತು ವಸ್ತುಗಳನ್ನು ಎಷ್ಟು ದೂರದಲ್ಲಿ ಎಳೆಯಲಾಗುತ್ತದೆ, ಸಾಮಾನ್ಯ ಪಾಲು.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "ಮುಚ್ಚಿದ ವಿಭಾಗಗಳ ಹಿಂದೆ ಮರೆಮಾಡಲಾಗಿರುವ ಭೂಪ್ರದೇಶವನ್ನು ಬಿಟ್ಟುಬಿಡುತ್ತದೆ. ಆಫ್ ಬಹಳಷ್ಟು ವೆಚ್ಚವಾಗುತ್ತದೆ.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "ಸುಧಾರಿತ",
|
||||
"Undo": "ರದ್ದುಮಾಡು",
|
||||
"Search options": "ಹುಡುಕಾಟ ಆಯ್ಕೆಗಳು",
|
||||
"Shortcut": "ಶಾರ್ಟ್ಕಟ್",
|
||||
"Distance": "ದೂರ",
|
||||
"Display": "ಪ್ರದರ್ಶನ",
|
||||
"Interface": "ಇಂಟರ್ಫೇಸ್",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "ಮಾಪನಾಂಕ ನಿರ್ಣಯಿಸಿ...",
|
||||
"Calibrate Anyway...": "ಹೇಗಾದರೂ ಮಾಪನಾಂಕ ಮಾಡಿ...",
|
||||
"Use Automatic Setup": "ಸ್ವಯಂಚಾಲಿತ ಸೆಟಪ್ ಬಳಸಿ",
|
||||
"Shortcut: %s": "ಶಾರ್ಟ್ಕಟ್: %s",
|
||||
"Next": "ಮುಂದೆ",
|
||||
"HDR Calibration %s/%s: %s": "HDR ಮಾಪನಾಂಕ ನಿರ್ಣಯ %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "ಮೂರು ಕೆಳಗಿನ ಪೂರ್ಣ ಪರದೆಯನ್ನು ಹೊಂದಿಸುತ್ತದೆ, ಒಂದು ಸಮಯದಲ್ಲಿ ಒಂದು ಪರೀಕ್ಷಾ ಚಿತ್ರ.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "ಆಟದಿಂದ ಈ ಪರದೆಯನ್ನು ತೆರೆಯುವ ಕೀ. ಮೊದಲಿಗೆ ಬದ್ಧವಾಗಿಲ್ಲ.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "ನಿಮ್ಮ ಡಿಸ್ಪ್ಲೇ ಅದು ಎಷ್ಟು ಪ್ರಕಾಶಮಾನವಾಗಿದೆ ಎಂದು ಹೇಳಿಲ್ಲ: ಅದನ್ನು ಹೊಂದಿಸಲು ಮಾಪನಾಂಕ ಮಾಡಿ.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "ನಿಮ್ಮ ಪ್ರದರ್ಶನಕ್ಕಾಗಿ ಈಗಾಗಲೇ ಹೊಂದಿಸಲಾಗಿದೆ. HDR ತಪ್ಪಾಗಿ ಕಂಡುಬಂದರೆ ಮಾತ್ರ ಮಾಪನಾಂಕ ನಿರ್ಣಯಿಸಿ.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "ಪೀಕ್ ಬ್ರೈಟ್ನೆಸ್ ಮತ್ತು ಪೇಪರ್ ವೈಟ್ ಅನ್ನು ನಿಮ್ಮ ಡಿಸ್ಪ್ಲೇಯ ಸೆಟಪ್ಗೆ ಹಿಂತಿರುಗಿಸುತ್ತದೆ.",
|
||||
|
||||
@@ -315,7 +315,6 @@
|
||||
"Sets the options below together. Changing one makes it Custom.": "아래 옵션들을 함께 설정합니다. 하나라도 변경하면 사용자 지정으로 전환됩니다.",
|
||||
"Lava, fire and sunlight shine brighter than white. Needs an HDR display.": "용암, 불, 햇빛이 흰색보다 더 밝게 빛납니다. HDR 디스플레이가 필요합니다.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "하라이트의 최대 밝기입니다. 자동: 시스템이 보고하는 최고 값입니다.",
|
||||
"How bright the HUD and menus are, against paper white.": "페이퍼 화이트 대비 HUD 및 메뉴의 밝기입니다.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "몹, 농작물, 기계가 계속 작동하는 거리입니다. CPU 시간이 소모됩니다.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "정상 대비 몹과 아이템이 그려지는 거리 비율입니다.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "닫힌 구역 뒤에 숨겨진 지형을 건너뜁니다. 끔으로 설정 시 성능 비용이 큽니다.",
|
||||
@@ -368,7 +367,6 @@
|
||||
"Advanced": "고급",
|
||||
"Undo": "실행 취소",
|
||||
"Search options": "옵션 검색",
|
||||
"Shortcut": "단축키",
|
||||
"Distance": "거리",
|
||||
"Display": "디스플레이",
|
||||
"Interface": "인터페이스",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "보정...",
|
||||
"Calibrate Anyway...": "그래도 보정...",
|
||||
"Use Automatic Setup": "자동 설정 사용",
|
||||
"Shortcut: %s": "단축키: %s",
|
||||
"Next": "다음",
|
||||
"HDR Calibration %s/%s: %s": "HDR 보정 %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "테스트 사진을 한 장씩 사용하여 아래 세 가지를 전체 화면으로 설정합니다.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "게임 내에서 이 화면을 여는 키입니다. 기본적으로 바인딩되어 있지 않습니다.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "디스플레이의 최대 밝기 정보가 없습니다. 설정하려면 보정하세요.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "디스플레이에 맞게 이미 설정되어 있습니다. HDR이 잘못 표시되는 경우에만 보정하세요.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "최대 밝기와 페이퍼 화이트를 디스플레이의 기본 설정으로 되돌립니다.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Көлөкөлөрдү дисплейиңиздин эң кара карасына көтөрөт. 0: чыныгы кара, көтөрүү жок.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "Кандай гана жаркыраган жерлер. Авто: тутумуңуздун эң жогорку көрсөткүчү.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Дүйнөдө ак кандай жарык көрүнөт. Авто: иш тактаңыздын актыгы.",
|
||||
"How bright the HUD and menus are, against paper white.": "Ак кагазга каршы HUD жана менюлар канчалык жарык.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Канчалык мобу, эгиндер жана машиналар иштей беришет. CPU убактысы.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Кадимкидей үлүшү катары, канча аралыкта мобдор жана буюмдар тартылат.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Жабык бөлүмдөрдүн артына жашырылган жерди өткөрүп жиберет. Чечим көп чыгымдалат.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Өркүндөтүлгөн",
|
||||
"Undo": "Жок кылуу",
|
||||
"Search options": "Издөө параметрлери",
|
||||
"Shortcut": "Жарлык",
|
||||
"Distance": "Дистанция",
|
||||
"Display": "Дисплей",
|
||||
"Interface": "Интерфейс",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Калибрлөө...",
|
||||
"Calibrate Anyway...": "Баары бир калибрлөө...",
|
||||
"Use Automatic Setup": "Автоматтык орнотууну колдонуңуз",
|
||||
"Shortcut: %s": "Кыска жол: %s",
|
||||
"Next": "Кийинки",
|
||||
"HDR Calibration %s/%s: %s": "HDR калибрлөө %s/%s: %s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Толук экрандын астындагы үчөөнү, бир убакта бир сыноо сүрөтүн орнотот.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Бул экранды оюндан ачкан ачкыч. Башында байланган эмес.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Дисплейде анын канчалык жарык болоору айтылган жок: аны жөндөө үчүн калибрлеңиз.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Дисплейиңиз үчүн мурунтан эле орнотулган. HDR туура эмес көрүнсө гана калибрлеңиз.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Дисплейиңиздин орнотулушуна эң жогорку жарыктык жана кагаз ак түсүн коет.",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Lifts shadows onto your display's darkest black. 0: true black, no lift.": "Umbras ad nigerrimum ostentus tui attollit. 0: vere nigrum, sine elevatione.",
|
||||
"How bright highlights get. Auto: the peak your system reports.": "quam claram lucem eg. Auto: ratio tua ad apicem refert.",
|
||||
"How bright white looks in the world. Auto: your desktop's white.": "Quam candidum album in mundo videatur. Automaticum: album scrinii tui.",
|
||||
"How bright the HUD and menus are, against paper white.": "Quam clara TESTA et menus sunt contra chartam albam.",
|
||||
"How far mobs, crops and machines keep working. CPU time.": "Quam longe turbas, fruges et machinis opus servant. CPU tempus.",
|
||||
"How far away mobs and items are drawn, as a share of normal.": "Quam procul sunt turbae et vasa ducuntur, ut communis pars.",
|
||||
"Skips terrain hidden behind closed sections. Off costs a lot.": "Skips locorum occultis sectionibus clausis. Off multum constat.",
|
||||
@@ -367,7 +366,6 @@
|
||||
"Advanced": "Provecta",
|
||||
"Undo": "Revoca",
|
||||
"Search options": "Quaerere optiones",
|
||||
"Shortcut": "Brevis",
|
||||
"Distance": "procul",
|
||||
"Display": "Ostendere",
|
||||
"Interface": "Interfacies",
|
||||
@@ -438,11 +436,9 @@
|
||||
"Calibrate...": "Calibrare...",
|
||||
"Calibrate Anyway...": "Calibrate Usquam...",
|
||||
"Use Automatic Setup": "Lorem Setup utere",
|
||||
"Shortcut: %s": "Brevis:%s",
|
||||
"Next": "Proximum",
|
||||
"HDR Calibration %s/%s: %s": "HDR Calibration%s/%s:%s",
|
||||
"Sets the three below full screen, one test picture at a time.": "Tres infra ponit tentorium plenum, unum tabula testium ad tempus.",
|
||||
"A key that opens this screen from the game. Not bound at first.": "Clavis quae hoc tegumentum a ludo aperit. Non primo tenetur.",
|
||||
"Your display didn't say how bright it gets: calibrate to set it up.": "Ostentatio tua non dixit quam clara accipit: calibrate ut eam erigat.",
|
||||
"Already set up for your display. Only calibrate if HDR looks wrong.": "Iam ad ostentationem tuam constitue. Tantum calibrate si HDR nefas spectat.",
|
||||
"Puts Peak Brightness and Paper White back to your display's setup.": "Ponit Peak Brightness et Chartam Albam reducere ad tui ostentationis setup.",
|
||||
|
||||