crimsonland 0.1.0.dev11__tar.gz → 0.1.0.dev13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/PKG-INFO +1 -1
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/pyproject.toml +1 -1
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/assets_fetch.py +23 -8
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/creatures/runtime.py +15 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/demo.py +47 -38
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/effects.py +46 -1
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/frontend/boot.py +2 -1
- crimsonland-0.1.0.dev13/src/crimson/frontend/high_scores_layout.py +26 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/frontend/menu.py +24 -43
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/frontend/panels/base.py +27 -29
- crimsonland-0.1.0.dev13/src/crimson/frontend/panels/controls.py +219 -0
- crimsonland-0.1.0.dev13/src/crimson/frontend/panels/credits.py +221 -0
- crimsonland-0.1.0.dev13/src/crimson/frontend/panels/databases.py +307 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/frontend/panels/mods.py +1 -3
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/frontend/panels/options.py +36 -42
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/frontend/panels/play_game.py +82 -74
- crimsonland-0.1.0.dev13/src/crimson/frontend/panels/stats.py +308 -0
- crimsonland-0.1.0.dev13/src/crimson/frontend/pause_menu.py +425 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/game.py +512 -505
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/gameplay.py +35 -6
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/modes/base_gameplay_mode.py +3 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/modes/quest_mode.py +54 -44
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/modes/rush_mode.py +4 -1
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/modes/survival_mode.py +15 -10
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/modes/tutorial_mode.py +15 -5
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/modes/typo_mode.py +4 -1
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/persistence/highscores.py +6 -2
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/render/world_renderer.py +1 -1
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/sim/world_state.py +8 -1
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/typo/spawns.py +3 -4
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/ui/demo_trial_overlay.py +3 -3
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/ui/game_over.py +18 -2
- crimsonland-0.1.0.dev13/src/crimson/ui/menu_panel.py +127 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/ui/perk_menu.py +101 -44
- crimsonland-0.1.0.dev13/src/crimson/ui/quest_results.py +669 -0
- crimsonland-0.1.0.dev13/src/crimson/ui/shadow.py +39 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/particles.py +1 -1
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/perk_menu_debug.py +2 -2
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/perks.py +2 -2
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/weapons.py +110 -110
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/app.py +3 -0
- crimsonland-0.1.0.dev11/src/crimson/frontend/panels/controls.py +0 -132
- crimsonland-0.1.0.dev11/src/crimson/frontend/panels/stats.py +0 -351
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/atlas.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/audio_router.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/bonuses.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/camera.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/cli.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/creatures/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/creatures/ai.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/creatures/anim.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/creatures/damage.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/creatures/spawn.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/debug.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/demo_trial.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/effects_atlas.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/frontend/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/frontend/assets.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/frontend/panels/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/frontend/transitions.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/game_modes.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/game_world.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/input_codes.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/modes/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/paths.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/perks.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/persistence/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/persistence/save_status.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/player_damage.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/projectiles.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/helpers.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/registry.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/results.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/runtime.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/tier1.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/tier2.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/tier3.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/tier4.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/tier5.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/timeline.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/quests/types.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/render/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/render/terrain_fx.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/sim/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/sim/world_defs.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/terrain_assets.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/tutorial/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/tutorial/timeline.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/typo/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/typo/names.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/typo/player.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/typo/typing.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/ui/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/ui/cursor.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/ui/hud.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/aim_debug.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/animations.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/arsenal_debug.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/audio_bootstrap.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/bonuses.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/camera_debug.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/camera_shake.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/corpse_stamp_debug.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/decals_debug.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/empty.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/fonts.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/game_over.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/ground.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/lighting_debug.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/player.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/player_sprite_debug.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/projectile_fx.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/projectile_render_debug.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/projectiles.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/quest_title_overlay.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/registry.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/rush.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/small_font_debug.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/spawn_plan.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/sprites.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/survival.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/terrain.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/ui.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/views/wicons.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/crimson/weapon_sfx.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/assets.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/audio.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/config.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/console.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/fonts/__init__.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/fonts/grim_mono.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/fonts/small.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/input.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/jaz.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/math.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/music.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/paq.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/rand.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/sfx.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/sfx_map.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/terrain_render.py +0 -0
- {crimsonland-0.1.0.dev11 → crimsonland-0.1.0.dev13}/src/grim/view.py +0 -0
|
@@ -2,7 +2,9 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
import os
|
|
5
6
|
import shutil
|
|
7
|
+
import tempfile
|
|
6
8
|
import urllib.request
|
|
7
9
|
|
|
8
10
|
from grim.console import ConsoleState
|
|
@@ -19,17 +21,30 @@ class DownloadResult:
|
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
def _download_file(url: str, dest: Path) -> None:
|
|
22
|
-
|
|
23
|
-
if tmp.exists():
|
|
24
|
-
tmp.unlink()
|
|
24
|
+
tmp_path: Path | None = None
|
|
25
25
|
try:
|
|
26
26
|
req = urllib.request.Request(url, headers={"User-Agent": "crimsonland-decompile"})
|
|
27
|
-
with urllib.request.urlopen(req, timeout=30) as resp
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
with urllib.request.urlopen(req, timeout=30) as resp:
|
|
28
|
+
with tempfile.NamedTemporaryFile(
|
|
29
|
+
mode="wb",
|
|
30
|
+
delete=False,
|
|
31
|
+
dir=dest.parent,
|
|
32
|
+
prefix=dest.name + ".",
|
|
33
|
+
suffix=".tmp",
|
|
34
|
+
) as handle:
|
|
35
|
+
tmp_path = Path(handle.name)
|
|
36
|
+
shutil.copyfileobj(resp, handle)
|
|
37
|
+
handle.flush()
|
|
38
|
+
os.fsync(handle.fileno())
|
|
39
|
+
if tmp_path is None:
|
|
40
|
+
raise RuntimeError("assets: temporary file not created")
|
|
41
|
+
tmp_path.replace(dest)
|
|
30
42
|
finally:
|
|
31
|
-
if
|
|
32
|
-
|
|
43
|
+
if tmp_path is not None:
|
|
44
|
+
try:
|
|
45
|
+
tmp_path.unlink()
|
|
46
|
+
except FileNotFoundError:
|
|
47
|
+
pass
|
|
33
48
|
|
|
34
49
|
|
|
35
50
|
def download_missing_paqs(
|
|
@@ -667,6 +667,21 @@ class CreaturePool:
|
|
|
667
667
|
elif perk_active(player, PerkId.VEINS_OF_POISON):
|
|
668
668
|
creature.flags |= CreatureFlags.SELF_DAMAGE_TICK
|
|
669
669
|
player_take_damage(state, player, float(creature.contact_damage), dt=dt, rand=rand)
|
|
670
|
+
if fx_queue is not None:
|
|
671
|
+
dx = float(player.pos_x) - float(creature.x)
|
|
672
|
+
dy = float(player.pos_y) - float(creature.y)
|
|
673
|
+
dist = math.hypot(dx, dy)
|
|
674
|
+
if dist > 1e-9:
|
|
675
|
+
dx /= dist
|
|
676
|
+
dy /= dist
|
|
677
|
+
else:
|
|
678
|
+
dx = 0.0
|
|
679
|
+
dy = 0.0
|
|
680
|
+
fx_queue.add_random(
|
|
681
|
+
pos_x=float(player.pos_x) + dx * 3.0,
|
|
682
|
+
pos_y=float(player.pos_y) + dy * 3.0,
|
|
683
|
+
rand=rand,
|
|
684
|
+
)
|
|
670
685
|
|
|
671
686
|
if (
|
|
672
687
|
bool(player.plaguebearer_active)
|
|
@@ -17,6 +17,7 @@ from grim.rand import Crand
|
|
|
17
17
|
from .game_world import GameWorld
|
|
18
18
|
from .gameplay import PlayerInput, PlayerState, weapon_assign_player
|
|
19
19
|
from .ui.cursor import draw_menu_cursor
|
|
20
|
+
from .ui.perk_menu import UiButtonState, UiButtonTextureSet, button_draw, button_update, button_width
|
|
20
21
|
from .weapons import WEAPON_TABLE, WeaponId, projectile_type_id_from_weapon_id, weapon_entry_for_projectile_type_id
|
|
21
22
|
|
|
22
23
|
WORLD_SIZE = 1024.0
|
|
@@ -123,6 +124,8 @@ class DemoView:
|
|
|
123
124
|
self._small_font: SmallFontData | None = None
|
|
124
125
|
self._purchase_active = False
|
|
125
126
|
self._purchase_url_opened = False
|
|
127
|
+
self._purchase_button = UiButtonState("Purchase", force_wide=True)
|
|
128
|
+
self._maybe_later_button = UiButtonState("Maybe later", force_wide=True)
|
|
126
129
|
self._spawn_rng = Crand(0)
|
|
127
130
|
|
|
128
131
|
def open(self) -> None:
|
|
@@ -131,6 +134,8 @@ class DemoView:
|
|
|
131
134
|
self._upsell_pulse_ms = 0
|
|
132
135
|
self._purchase_active = False
|
|
133
136
|
self._purchase_url_opened = False
|
|
137
|
+
self._purchase_button = UiButtonState("Purchase", force_wide=True)
|
|
138
|
+
self._maybe_later_button = UiButtonState("Maybe later", force_wide=True)
|
|
134
139
|
self._variant_index = 0
|
|
135
140
|
self._demo_variant_index = 0
|
|
136
141
|
self._quest_spawn_timeline_ms = 0
|
|
@@ -166,7 +171,7 @@ class DemoView:
|
|
|
166
171
|
|
|
167
172
|
if self._purchase_active:
|
|
168
173
|
self._upsell_pulse_ms += frame_dt_ms
|
|
169
|
-
self._update_purchase_screen()
|
|
174
|
+
self._update_purchase_screen(frame_dt_ms)
|
|
170
175
|
self._quest_spawn_timeline_ms += frame_dt_ms
|
|
171
176
|
if self._quest_spawn_timeline_ms > self._demo_time_limit_ms:
|
|
172
177
|
# demo_purchase_screen_update restarts the demo once the purchase screen
|
|
@@ -214,6 +219,8 @@ class DemoView:
|
|
|
214
219
|
self._quest_spawn_timeline_ms = 0
|
|
215
220
|
self._demo_time_limit_ms = max(0, int(limit_ms))
|
|
216
221
|
self._purchase_url_opened = False
|
|
222
|
+
self._purchase_button = UiButtonState("Purchase", force_wide=True)
|
|
223
|
+
self._maybe_later_button = UiButtonState("Maybe later", force_wide=True)
|
|
217
224
|
|
|
218
225
|
def _ensure_small_font(self) -> SmallFontData:
|
|
219
226
|
if self._small_font is not None:
|
|
@@ -230,18 +237,20 @@ class DemoView:
|
|
|
230
237
|
return 128.0
|
|
231
238
|
return 0.0
|
|
232
239
|
|
|
233
|
-
def _update_purchase_screen(self) -> None:
|
|
240
|
+
def _update_purchase_screen(self, dt_ms: int) -> None:
|
|
241
|
+
dt_ms = max(0, int(dt_ms))
|
|
234
242
|
if rl.is_key_pressed(rl.KeyboardKey.KEY_ESCAPE):
|
|
235
243
|
self._purchase_active = False
|
|
236
244
|
self._finished = True
|
|
237
245
|
return
|
|
238
246
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
247
|
+
font = self._ensure_small_font()
|
|
248
|
+
cache = self._ensure_cache()
|
|
249
|
+
textures = UiButtonTextureSet(
|
|
250
|
+
button_sm=cache.get_or_load("ui_buttonSm", "ui/ui_button_64x32.jaz").texture,
|
|
251
|
+
button_md=cache.get_or_load("ui_buttonMd", "ui/ui_button_128x32.jaz").texture,
|
|
252
|
+
)
|
|
253
|
+
if textures.button_sm is None and textures.button_md is None:
|
|
245
254
|
return
|
|
246
255
|
|
|
247
256
|
w = float(self._state.config.screen_width)
|
|
@@ -252,14 +261,18 @@ class DemoView:
|
|
|
252
261
|
purchase_y = button_base_y + 50.0
|
|
253
262
|
maybe_y = button_base_y + 90.0
|
|
254
263
|
|
|
255
|
-
purchase_rect = rl.Rectangle(button_x, purchase_y, float(button_tex.width), float(button_tex.height))
|
|
256
|
-
maybe_rect = rl.Rectangle(button_x, maybe_y, float(button_tex.width), float(button_tex.height))
|
|
257
|
-
|
|
258
264
|
mouse = rl.get_mouse_position()
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
265
|
+
click = rl.is_mouse_button_pressed(rl.MouseButton.MOUSE_BUTTON_LEFT)
|
|
266
|
+
scale = 1.0
|
|
267
|
+
button_w = button_width(font, self._purchase_button.label, scale=scale, force_wide=self._purchase_button.force_wide)
|
|
268
|
+
if button_update(
|
|
269
|
+
self._purchase_button,
|
|
270
|
+
x=float(button_x),
|
|
271
|
+
y=float(purchase_y),
|
|
272
|
+
width=float(button_w),
|
|
273
|
+
dt_ms=float(dt_ms),
|
|
274
|
+
mouse=mouse,
|
|
275
|
+
click=bool(click),
|
|
263
276
|
):
|
|
264
277
|
if not self._purchase_url_opened:
|
|
265
278
|
self._purchase_url_opened = True
|
|
@@ -272,10 +285,14 @@ class DemoView:
|
|
|
272
285
|
if hasattr(self._state, "quit_requested"):
|
|
273
286
|
self._state.quit_requested = True
|
|
274
287
|
|
|
275
|
-
if (
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
288
|
+
if button_update(
|
|
289
|
+
self._maybe_later_button,
|
|
290
|
+
x=float(button_x),
|
|
291
|
+
y=float(maybe_y),
|
|
292
|
+
width=float(button_w),
|
|
293
|
+
dt_ms=float(dt_ms),
|
|
294
|
+
mouse=mouse,
|
|
295
|
+
click=bool(click),
|
|
279
296
|
):
|
|
280
297
|
self._purchase_active = False
|
|
281
298
|
self._finished = True
|
|
@@ -294,8 +311,8 @@ class DemoView:
|
|
|
294
311
|
if hasattr(self._state, "quit_requested"):
|
|
295
312
|
self._state.quit_requested = True
|
|
296
313
|
|
|
297
|
-
# Keep
|
|
298
|
-
_ =
|
|
314
|
+
# Keep referenced to avoid unused warnings if this method grows.
|
|
315
|
+
_ = textures
|
|
299
316
|
|
|
300
317
|
def _draw_purchase_screen(self) -> None:
|
|
301
318
|
rl.clear_background(rl.BLACK)
|
|
@@ -393,29 +410,21 @@ class DemoView:
|
|
|
393
410
|
|
|
394
411
|
# Buttons on the right.
|
|
395
412
|
cache = self._ensure_cache()
|
|
396
|
-
|
|
397
|
-
|
|
413
|
+
textures = UiButtonTextureSet(
|
|
414
|
+
button_sm=cache.get_or_load("ui_buttonSm", "ui/ui_button_64x32.jaz").texture,
|
|
415
|
+
button_md=cache.get_or_load("ui_buttonMd", "ui/ui_button_128x32.jaz").texture,
|
|
416
|
+
)
|
|
417
|
+
if textures.button_sm is None and textures.button_md is None:
|
|
398
418
|
return
|
|
399
419
|
|
|
400
420
|
button_x = screen_w / 2.0 + 128.0
|
|
401
421
|
button_base_y = screen_h / 2.0 + 102.0 + wide_shift * 0.3
|
|
402
422
|
purchase_y = button_base_y + 50.0
|
|
403
423
|
maybe_y = button_base_y + 90.0
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
tint = rl.Color(255, 255, 255, 255) if hovered else rl.Color(220, 220, 220, 255)
|
|
409
|
-
rl.draw_texture(texture, int(x), int(y0), tint)
|
|
410
|
-
label_scale = 1.0
|
|
411
|
-
text_w = measure_small_text_width(small, label, label_scale)
|
|
412
|
-
text_x = x + float(texture.width) * 0.5 - text_w * 0.5 + 1.0
|
|
413
|
-
text_y = y0 + 10.0
|
|
414
|
-
alpha = 1.0 if hovered else 0.7
|
|
415
|
-
draw_small_text(small, label, text_x, text_y, label_scale, rl.Color(255, 255, 255, int(255 * alpha)))
|
|
416
|
-
|
|
417
|
-
draw_button(button_tex, "Purchase", button_x, purchase_y)
|
|
418
|
-
draw_button(button_tex, "Maybe later", button_x, maybe_y)
|
|
424
|
+
scale = 1.0
|
|
425
|
+
button_w = button_width(small, self._purchase_button.label, scale=scale, force_wide=self._purchase_button.force_wide)
|
|
426
|
+
button_draw(textures, small, self._purchase_button, x=button_x, y=purchase_y, width=button_w, scale=scale)
|
|
427
|
+
button_draw(textures, small, self._maybe_later_button, x=button_x, y=maybe_y, width=button_w, scale=scale)
|
|
419
428
|
|
|
420
429
|
# Demo purchase screen uses menu-style cursor; draw it explicitly since the OS cursor is hidden.
|
|
421
430
|
particles = cache.get_or_load("particles", "game/particles.jaz").texture
|
|
@@ -209,7 +209,7 @@ class ParticlePool:
|
|
|
209
209
|
|
|
210
210
|
size = float(getattr(creature, "size", 50.0))
|
|
211
211
|
dist = math.hypot(float(getattr(creature, "x", 0.0)) - pos_x, float(getattr(creature, "y", 0.0)) - pos_y) - radius
|
|
212
|
-
threshold = size * 0.
|
|
212
|
+
threshold = size * 0.14285715 + 3.0
|
|
213
213
|
if threshold < dist:
|
|
214
214
|
continue
|
|
215
215
|
return int(creature_idx)
|
|
@@ -721,6 +721,51 @@ class EffectPool:
|
|
|
721
721
|
|
|
722
722
|
self.free(idx)
|
|
723
723
|
|
|
724
|
+
def spawn_shell_casing(
|
|
725
|
+
self,
|
|
726
|
+
*,
|
|
727
|
+
pos_x: float,
|
|
728
|
+
pos_y: float,
|
|
729
|
+
aim_heading: float,
|
|
730
|
+
weapon_flags: int,
|
|
731
|
+
rand: Callable[[], int],
|
|
732
|
+
detail_preset: int,
|
|
733
|
+
) -> None:
|
|
734
|
+
"""Port of the casing spawn in `player_update` (effect_id 0x12)."""
|
|
735
|
+
|
|
736
|
+
if (int(weapon_flags) & 0x1) == 0:
|
|
737
|
+
return
|
|
738
|
+
|
|
739
|
+
angle = float(aim_heading) + float(int(rand()) & 0x3F) * 0.01
|
|
740
|
+
speed = float(int(rand()) & 0x3F) * 0.022727273 + 1.0
|
|
741
|
+
vel_x = math.cos(angle) * speed * 100.0
|
|
742
|
+
vel_y = math.sin(angle) * speed * 100.0
|
|
743
|
+
|
|
744
|
+
rotation = float((int(rand()) & 0x3F) - 0x20) * 0.1
|
|
745
|
+
rotation_step = (float(int(rand()) % 0x14) * 0.1 - 1.0) * 14.0
|
|
746
|
+
|
|
747
|
+
self.spawn(
|
|
748
|
+
effect_id=0x12,
|
|
749
|
+
pos_x=float(pos_x),
|
|
750
|
+
pos_y=float(pos_y),
|
|
751
|
+
vel_x=float(vel_x),
|
|
752
|
+
vel_y=float(vel_y),
|
|
753
|
+
rotation=float(rotation),
|
|
754
|
+
scale=1.0,
|
|
755
|
+
half_width=2.0,
|
|
756
|
+
half_height=2.0,
|
|
757
|
+
age=0.0,
|
|
758
|
+
lifetime=0.15,
|
|
759
|
+
flags=0x1C5,
|
|
760
|
+
color_r=1.0,
|
|
761
|
+
color_g=1.0,
|
|
762
|
+
color_b=1.0,
|
|
763
|
+
color_a=0.6,
|
|
764
|
+
rotation_step=float(rotation_step),
|
|
765
|
+
scale_step=0.0,
|
|
766
|
+
detail_preset=int(detail_preset),
|
|
767
|
+
)
|
|
768
|
+
|
|
724
769
|
def spawn_blood_splatter(
|
|
725
770
|
self,
|
|
726
771
|
*,
|
|
@@ -118,7 +118,8 @@ MENU_PREP_TEXTURES: tuple[tuple[str, str], ...] = (
|
|
|
118
118
|
("ui_checkOff", "ui/ui_checkOff.jaz"),
|
|
119
119
|
("ui_rectOff", "ui/ui_rectOff.jaz"),
|
|
120
120
|
("ui_rectOn", "ui/ui_rectOn.jaz"),
|
|
121
|
-
("
|
|
121
|
+
("ui_buttonSm", "ui/ui_button_64x32.jaz"),
|
|
122
|
+
("ui_buttonMd", "ui/ui_button_128x32.jaz"),
|
|
122
123
|
)
|
|
123
124
|
|
|
124
125
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Layout constants for the classic high scores screen (state_id=14).
|
|
3
|
+
|
|
4
|
+
Measured from analysis/frida/ui_render_trace_oracle_1024x768.json.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
# Panel positions are expressed in "panel pos" (pre-offset) space, matching other menu panels:
|
|
10
|
+
# panel_top_left = (panel_pos_x + MENU_PANEL_OFFSET_X, panel_pos_y + y_shift + MENU_PANEL_OFFSET_Y)
|
|
11
|
+
|
|
12
|
+
HS_LEFT_PANEL_POS_X = -119.0
|
|
13
|
+
HS_LEFT_PANEL_POS_Y = 185.0
|
|
14
|
+
HS_LEFT_PANEL_HEIGHT = 378.0
|
|
15
|
+
|
|
16
|
+
HS_RIGHT_PANEL_POS_X = 609.0
|
|
17
|
+
HS_RIGHT_PANEL_POS_Y = 200.0
|
|
18
|
+
HS_RIGHT_PANEL_HEIGHT = 254.0
|
|
19
|
+
|
|
20
|
+
# Buttons inside the left panel (relative to the left panel top-left).
|
|
21
|
+
HS_BUTTON_X = 234.0 # x0=136 at 1024x768
|
|
22
|
+
HS_BUTTON_Y0 = 268.0 # y0=462
|
|
23
|
+
HS_BUTTON_STEP_Y = 33.0
|
|
24
|
+
|
|
25
|
+
HS_BACK_BUTTON_X = 400.0 # x0=302
|
|
26
|
+
HS_BACK_BUTTON_Y = 301.0 # y0=495
|
|
@@ -11,6 +11,7 @@ from grim.audio import play_music, play_sfx, stop_music, update_audio
|
|
|
11
11
|
from grim.terrain_render import GroundRenderer
|
|
12
12
|
|
|
13
13
|
from ..ui.cursor import draw_menu_cursor
|
|
14
|
+
from ..ui.shadow import UI_SHADOW_OFFSET, UI_SHADOW_TINT, draw_ui_quad_shadow # noqa: F401
|
|
14
15
|
from .assets import MenuAssets, _ensure_texture_cache, load_menu_assets
|
|
15
16
|
from .transitions import _draw_screen_fade
|
|
16
17
|
|
|
@@ -18,8 +19,8 @@ if TYPE_CHECKING:
|
|
|
18
19
|
from ..game import GameState
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
MENU_LABEL_WIDTH =
|
|
22
|
-
MENU_LABEL_HEIGHT =
|
|
22
|
+
MENU_LABEL_WIDTH = 122.0
|
|
23
|
+
MENU_LABEL_HEIGHT = 28.0
|
|
23
24
|
MENU_LABEL_ROW_HEIGHT = 32.0
|
|
24
25
|
MENU_LABEL_ROW_PLAY_GAME = 1
|
|
25
26
|
MENU_LABEL_ROW_OPTIONS = 2
|
|
@@ -30,15 +31,17 @@ MENU_LABEL_ROW_QUIT = 6
|
|
|
30
31
|
MENU_LABEL_ROW_BACK = 7
|
|
31
32
|
MENU_LABEL_BASE_X = -60.0
|
|
32
33
|
MENU_LABEL_BASE_Y = 210.0
|
|
33
|
-
MENU_LABEL_OFFSET_X =
|
|
34
|
-
MENU_LABEL_OFFSET_Y = -
|
|
34
|
+
MENU_LABEL_OFFSET_X = 271.0
|
|
35
|
+
MENU_LABEL_OFFSET_Y = -37.0
|
|
35
36
|
MENU_LABEL_STEP = 60.0
|
|
36
|
-
MENU_ITEM_OFFSET_X = -
|
|
37
|
-
MENU_ITEM_OFFSET_Y = -
|
|
38
|
-
MENU_PANEL_WIDTH =
|
|
39
|
-
MENU_PANEL_HEIGHT =
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
MENU_ITEM_OFFSET_X = -71.0
|
|
38
|
+
MENU_ITEM_OFFSET_Y = -59.0
|
|
39
|
+
MENU_PANEL_WIDTH = 510.0
|
|
40
|
+
MENU_PANEL_HEIGHT = 254.0
|
|
41
|
+
# Measured from ui_render_trace at 1024x768 (stable timeline):
|
|
42
|
+
# panel top-left is (pos_x + 21, pos_y - 81) and size is 510x254, plus a shadow pass at +7,+7.
|
|
43
|
+
MENU_PANEL_OFFSET_X = 21.0
|
|
44
|
+
MENU_PANEL_OFFSET_Y = -81.0
|
|
42
45
|
MENU_PANEL_BASE_X = -45.0
|
|
43
46
|
MENU_PANEL_BASE_Y = 210.0
|
|
44
47
|
MENU_SCALE_SMALL_THRESHOLD = 640
|
|
@@ -48,15 +51,10 @@ MENU_SCALE_SMALL = 0.8
|
|
|
48
51
|
MENU_SCALE_LARGE = 1.2
|
|
49
52
|
MENU_SCALE_SHIFT = 10.0
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
MENU_SIGN_WIDTH = 573.44
|
|
57
|
-
MENU_SIGN_HEIGHT = 143.36
|
|
58
|
-
MENU_SIGN_OFFSET_X = -577.44
|
|
59
|
-
MENU_SIGN_OFFSET_Y = -62.0
|
|
54
|
+
MENU_SIGN_WIDTH = 571.44
|
|
55
|
+
MENU_SIGN_HEIGHT = 141.36
|
|
56
|
+
MENU_SIGN_OFFSET_X = -576.44
|
|
57
|
+
MENU_SIGN_OFFSET_Y = -61.0
|
|
60
58
|
MENU_SIGN_POS_Y = 70.0
|
|
61
59
|
MENU_SIGN_POS_Y_SMALL = 60.0
|
|
62
60
|
MENU_SIGN_POS_X_PAD = 4.0
|
|
@@ -585,21 +583,24 @@ class MenuView:
|
|
|
585
583
|
start_ms: int,
|
|
586
584
|
end_ms: int,
|
|
587
585
|
width: float,
|
|
586
|
+
direction_flag: int = 0,
|
|
588
587
|
) -> tuple[float, float]:
|
|
589
588
|
# Matches ui_element_update: angle lerps pi/2 -> 0 over [end_ms, start_ms].
|
|
590
|
-
#
|
|
589
|
+
# direction_flag=0 slides from left (-width -> 0)
|
|
590
|
+
# direction_flag=1 slides from right (+width -> 0)
|
|
591
591
|
if start_ms <= end_ms or width <= 0.0:
|
|
592
592
|
return 0.0, 0.0
|
|
593
|
+
dir_sign = 1.0 if int(direction_flag) else -1.0
|
|
593
594
|
t = self._timeline_ms
|
|
594
595
|
if t < end_ms:
|
|
595
596
|
angle = 1.5707964
|
|
596
|
-
offset_x =
|
|
597
|
+
offset_x = dir_sign * abs(width)
|
|
597
598
|
elif t < start_ms:
|
|
598
599
|
elapsed = t - end_ms
|
|
599
600
|
span = float(start_ms - end_ms)
|
|
600
601
|
p = float(elapsed) / span
|
|
601
602
|
angle = 1.5707964 * (1.0 - p)
|
|
602
|
-
offset_x =
|
|
603
|
+
offset_x = dir_sign * ((1.0 - p) * abs(width))
|
|
603
604
|
else:
|
|
604
605
|
angle = 0.0
|
|
605
606
|
offset_x = 0.0
|
|
@@ -628,27 +629,7 @@ class MenuView:
|
|
|
628
629
|
origin: rl.Vector2,
|
|
629
630
|
rotation_deg: float,
|
|
630
631
|
) -> None:
|
|
631
|
-
|
|
632
|
-
# only apply them when switching the blend mode.
|
|
633
|
-
rl.rl_set_blend_factors_separate(
|
|
634
|
-
rl.RL_ZERO,
|
|
635
|
-
rl.RL_ONE_MINUS_SRC_ALPHA,
|
|
636
|
-
rl.RL_ZERO,
|
|
637
|
-
rl.RL_ONE,
|
|
638
|
-
rl.RL_FUNC_ADD,
|
|
639
|
-
rl.RL_FUNC_ADD,
|
|
640
|
-
)
|
|
641
|
-
rl.begin_blend_mode(rl.BLEND_CUSTOM_SEPARATE)
|
|
642
|
-
rl.rl_set_blend_factors_separate(
|
|
643
|
-
rl.RL_ZERO,
|
|
644
|
-
rl.RL_ONE_MINUS_SRC_ALPHA,
|
|
645
|
-
rl.RL_ZERO,
|
|
646
|
-
rl.RL_ONE,
|
|
647
|
-
rl.RL_FUNC_ADD,
|
|
648
|
-
rl.RL_FUNC_ADD,
|
|
649
|
-
)
|
|
650
|
-
rl.draw_texture_pro(texture, src, dst, origin, rotation_deg, UI_SHADOW_TINT)
|
|
651
|
-
rl.end_blend_mode()
|
|
632
|
+
draw_ui_quad_shadow(texture=texture, src=src, dst=dst, origin=origin, rotation_deg=rotation_deg)
|
|
652
633
|
|
|
653
634
|
def _draw_menu_sign(self) -> None:
|
|
654
635
|
assets = self._assets
|
|
@@ -8,6 +8,7 @@ from grim.assets import PaqTextureCache
|
|
|
8
8
|
from grim.audio import play_sfx, update_audio
|
|
9
9
|
from grim.terrain_render import GroundRenderer
|
|
10
10
|
|
|
11
|
+
from ...ui.menu_panel import draw_classic_menu_panel
|
|
11
12
|
from ..assets import MenuAssets, _ensure_texture_cache, load_menu_assets
|
|
12
13
|
from ..menu import (
|
|
13
14
|
MENU_ITEM_OFFSET_X,
|
|
@@ -70,6 +71,9 @@ class PanelMenuView:
|
|
|
70
71
|
body: str | None = None,
|
|
71
72
|
panel_pos_x: float = PANEL_POS_X,
|
|
72
73
|
panel_pos_y: float = PANEL_POS_Y,
|
|
74
|
+
panel_offset_x: float = MENU_PANEL_OFFSET_X,
|
|
75
|
+
panel_offset_y: float = MENU_PANEL_OFFSET_Y,
|
|
76
|
+
panel_height: float = MENU_PANEL_HEIGHT,
|
|
73
77
|
back_pos_x: float = PANEL_BACK_POS_X,
|
|
74
78
|
back_pos_y: float = PANEL_BACK_POS_Y,
|
|
75
79
|
back_action: str = "back_to_menu",
|
|
@@ -79,6 +83,9 @@ class PanelMenuView:
|
|
|
79
83
|
self._body_lines = (body or "").splitlines()
|
|
80
84
|
self._panel_pos_x = panel_pos_x
|
|
81
85
|
self._panel_pos_y = panel_pos_y
|
|
86
|
+
self._panel_offset_x = panel_offset_x
|
|
87
|
+
self._panel_offset_y = panel_offset_y
|
|
88
|
+
self._panel_height = panel_height
|
|
82
89
|
self._back_pos_x = back_pos_x
|
|
83
90
|
self._back_pos_y = back_pos_y
|
|
84
91
|
self._back_action = back_action
|
|
@@ -163,9 +170,7 @@ class PanelMenuView:
|
|
|
163
170
|
entry.ready_timer_ms = min(0x100, entry.ready_timer_ms + dt_ms)
|
|
164
171
|
|
|
165
172
|
def draw(self) -> None:
|
|
166
|
-
|
|
167
|
-
if self._ground is not None:
|
|
168
|
-
self._ground.draw(0.0, 0.0)
|
|
173
|
+
self._draw_background()
|
|
169
174
|
_draw_screen_fade(self._state)
|
|
170
175
|
assets = self._assets
|
|
171
176
|
entry = self._entry
|
|
@@ -206,47 +211,40 @@ class PanelMenuView:
|
|
|
206
211
|
return _ensure_texture_cache(self._state)
|
|
207
212
|
|
|
208
213
|
def _init_ground(self) -> None:
|
|
214
|
+
if self._state.pause_background is not None:
|
|
215
|
+
self._ground = None
|
|
216
|
+
return
|
|
209
217
|
self._ground = ensure_menu_ground(self._state)
|
|
210
218
|
|
|
219
|
+
def _draw_background(self) -> None:
|
|
220
|
+
rl.clear_background(rl.BLACK)
|
|
221
|
+
pause_background = self._state.pause_background
|
|
222
|
+
if pause_background is not None:
|
|
223
|
+
pause_background.draw_pause_background()
|
|
224
|
+
return
|
|
225
|
+
if self._ground is not None:
|
|
226
|
+
self._ground.draw(0.0, 0.0)
|
|
227
|
+
|
|
211
228
|
def _draw_panel(self) -> None:
|
|
212
229
|
assets = self._assets
|
|
213
230
|
if assets is None or assets.panel is None:
|
|
214
231
|
return
|
|
215
232
|
panel = assets.panel
|
|
216
|
-
panel_w = MENU_PANEL_WIDTH
|
|
217
|
-
panel_h = MENU_PANEL_HEIGHT
|
|
218
233
|
_angle_rad, slide_x = MenuView._ui_element_anim(
|
|
219
234
|
self,
|
|
220
235
|
index=1,
|
|
221
236
|
start_ms=PANEL_TIMELINE_START_MS,
|
|
222
237
|
end_ms=PANEL_TIMELINE_END_MS,
|
|
223
|
-
width=
|
|
238
|
+
width=MENU_PANEL_WIDTH * self._menu_item_scale(0)[0],
|
|
224
239
|
)
|
|
225
240
|
item_scale, _local_y_shift = self._menu_item_scale(0)
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
)
|
|
232
|
-
origin = rl.Vector2(-(MENU_PANEL_OFFSET_X * item_scale), -(MENU_PANEL_OFFSET_Y * item_scale))
|
|
241
|
+
panel_w = MENU_PANEL_WIDTH * item_scale
|
|
242
|
+
panel_h = float(self._panel_height) * item_scale
|
|
243
|
+
top_left_x = self._panel_pos_x + slide_x + self._panel_offset_x * item_scale
|
|
244
|
+
top_left_y = self._panel_pos_y + self._widescreen_y_shift + self._panel_offset_y * item_scale
|
|
245
|
+
dst = rl.Rectangle(float(top_left_x), float(top_left_y), float(panel_w), float(panel_h))
|
|
233
246
|
fx_detail = bool(self._state.config.data.get("fx_detail_0", 0))
|
|
234
|
-
|
|
235
|
-
MenuView._draw_ui_quad_shadow(
|
|
236
|
-
texture=panel,
|
|
237
|
-
src=rl.Rectangle(0.0, 0.0, float(panel.width), float(panel.height)),
|
|
238
|
-
dst=rl.Rectangle(dst.x + UI_SHADOW_OFFSET, dst.y + UI_SHADOW_OFFSET, dst.width, dst.height),
|
|
239
|
-
origin=origin,
|
|
240
|
-
rotation_deg=0.0,
|
|
241
|
-
)
|
|
242
|
-
MenuView._draw_ui_quad(
|
|
243
|
-
texture=panel,
|
|
244
|
-
src=rl.Rectangle(0.0, 0.0, float(panel.width), float(panel.height)),
|
|
245
|
-
dst=dst,
|
|
246
|
-
origin=origin,
|
|
247
|
-
rotation_deg=0.0,
|
|
248
|
-
tint=rl.WHITE,
|
|
249
|
-
)
|
|
247
|
+
draw_classic_menu_panel(panel, dst=dst, tint=rl.WHITE, shadow=fx_detail)
|
|
250
248
|
|
|
251
249
|
def _draw_entry(self, entry: MenuEntry) -> None:
|
|
252
250
|
assets = self._assets
|