frontengine 1.0.3__tar.gz → 1.0.5__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.
- {frontengine-1.0.3 → frontengine-1.0.5}/PKG-INFO +1 -1
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/pet/desktop_pet.py +209 -30
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/pet/pet_setting_ui.py +49 -11
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/english.py +4 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/traditional_chinese.py +4 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine.egg-info/PKG-INFO +1 -1
- {frontengine-1.0.3 → frontengine-1.0.5}/pyproject.toml +1 -1
- {frontengine-1.0.3 → frontengine-1.0.5}/LICENSE +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/README.md +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/__main__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/base_widget.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/gif/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/gif/paint_gif.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/image/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/image/paint_image.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/load/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/load/load_someone_make_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/overlay_factory.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/particle/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/particle/particle_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/pet/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/scene/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/scene/extend_graphic_scene.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/scene/extend_graphic_view.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/scene/scene.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/sound_player/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/sound_player/sound_effect.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/sound_player/sound_player.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/text/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/text/draw_text.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/video/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/video/video_player.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/web/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/web/webview.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/show/window_helpers.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/system_tray/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/system_tray/extend_system_tray.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/color/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/color/global_color.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/dialog/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/dialog/choose_file_dialog.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/dialog/hotkey_settings_dialog.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/dialog/save_file_dialog.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/main_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/menu/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/menu/help_menu.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/menu/how_to_menu.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/menu/language_menu.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/menu/preset_menu.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/menu/settings_menu.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/control_center/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/control_center/control_center_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/gif/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/gif/gif_setting_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/image/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/image/image_setting_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/particle/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/particle/particle_setting_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/pet/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_manager.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/gif.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/image.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/registry.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/sound.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/text.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/video.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/web.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_setting_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/sound_player/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/sound_player/sound_player_setting_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/text/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/text/text_setting_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/utils.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/video/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/video/video_setting_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/web/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/web/web_setting_ui.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/user_setting/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/user_setting/preset_repository.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/user_setting/scene_setting.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/user_setting/user_setting_file.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/browser/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/browser/browser.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/critical_exit/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/critical_exit/check_key_is_press.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/critical_exit/critical_exit.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/critical_exit/win32_vk.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/exception/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/exception/exception_tags.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/exception/exceptions.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/file/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/file/open/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/file/open/open_file.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/file/save/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/file/save/save_file.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/hotkey/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/hotkey/hotkey_service.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/json/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/json/json_file.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/json/json_repository.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/json_format/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/json_format/json_process.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/logging/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/logging/loggin_instance.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/france.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/germany.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/italy.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/language_wrapper.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/russian.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/simplified_chinese.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/preset_schedule/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/preset_schedule/preset_schedule_service.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/redirect_manager/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/redirect_manager/redirect_manager_class.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/smart_pause/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/smart_pause/smart_pause_service.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/theme_schedule/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/theme_schedule/theme_schedule_service.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/web_url.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/worker/__init__.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine/worker/qthread_worker.py +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine.egg-info/SOURCES.txt +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine.egg-info/dependency_links.txt +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine.egg-info/entry_points.txt +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine.egg-info/requires.txt +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/frontengine.egg-info/top_level.txt +0 -0
- {frontengine-1.0.3 → frontengine-1.0.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frontengine
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.5
|
|
4
4
|
Summary: FrontEngine is use-define frontview or only use like screen saver
|
|
5
5
|
Author-email: JE-Chen <jechenmailman@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/Intergration-Automation-Testing/FrontEngine
|
|
@@ -2,7 +2,7 @@ import random as _random_module
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from typing import Optional, Tuple
|
|
4
4
|
|
|
5
|
-
from PySide6.QtCore import Qt, QRect, QTimer
|
|
5
|
+
from PySide6.QtCore import Qt, QRect, QTimer, Signal
|
|
6
6
|
from PySide6.QtGui import QAction, QCursor, QMovie, QPainter, QPixmap, QTransform
|
|
7
7
|
from PySide6.QtWidgets import QMenu, QMessageBox
|
|
8
8
|
|
|
@@ -16,6 +16,69 @@ BEHAVIOUR_FLOOR = "floor" # walk on the floor with gravity, throw & bounce
|
|
|
16
16
|
BEHAVIOUR_WANDER = "wander" # free 2D bounce, no gravity
|
|
17
17
|
BEHAVIOUR_CHASE = "chase" # chase the mouse cursor, sleep when caught
|
|
18
18
|
|
|
19
|
+
# 攀爬時所在的表面 / Surface the pet is crawling on while climbing
|
|
20
|
+
SURFACE_FLOOR = "floor"
|
|
21
|
+
SURFACE_LEFT = "left"
|
|
22
|
+
SURFACE_CEILING = "ceiling"
|
|
23
|
+
SURFACE_RIGHT = "right"
|
|
24
|
+
|
|
25
|
+
# 視覺狀態(決定顯示哪張精靈)/ Visual states (which sprite to show)
|
|
26
|
+
STATE_WALK = "walk"
|
|
27
|
+
STATE_IDLE = "idle"
|
|
28
|
+
STATE_CLIMB = "climb"
|
|
29
|
+
STATE_FALL = "fall"
|
|
30
|
+
STATE_DRAG = "drag"
|
|
31
|
+
|
|
32
|
+
# 動作包(資料夾)中,各狀態可接受的檔名(不含副檔名,先命中者為準)
|
|
33
|
+
# Accepted file stems per state inside a pet pack folder (first match wins).
|
|
34
|
+
_PACK_STATE_ALIASES = {
|
|
35
|
+
STATE_WALK: ("walk", "run", "move"),
|
|
36
|
+
STATE_IDLE: ("idle", "sit", "stand", "sleep"),
|
|
37
|
+
STATE_CLIMB: ("climb", "grab", "wall"),
|
|
38
|
+
STATE_FALL: ("fall", "jump"),
|
|
39
|
+
STATE_DRAG: ("drag", "pinch", "grabbed", "held"),
|
|
40
|
+
}
|
|
41
|
+
_PACK_EXTS = (".gif", ".webp", ".png", ".jpg", ".jpeg")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def scan_pet_pack(folder: str) -> dict:
|
|
45
|
+
"""
|
|
46
|
+
掃描動作包資料夾,回傳「視覺狀態 -> 圖片路徑」對應。非資料夾回傳空 dict。
|
|
47
|
+
Scan a pet-pack folder and return a ``state -> image path`` mapping.
|
|
48
|
+
Returns {} when `folder` is not a directory.
|
|
49
|
+
"""
|
|
50
|
+
result: dict = {}
|
|
51
|
+
try:
|
|
52
|
+
folder_path = Path(folder)
|
|
53
|
+
if not folder_path.is_dir():
|
|
54
|
+
return result
|
|
55
|
+
by_stem = {
|
|
56
|
+
path.stem.lower(): path
|
|
57
|
+
for path in sorted(folder_path.iterdir())
|
|
58
|
+
if path.is_file() and path.suffix.lower() in _PACK_EXTS
|
|
59
|
+
}
|
|
60
|
+
for state, aliases in _PACK_STATE_ALIASES.items():
|
|
61
|
+
for alias in aliases:
|
|
62
|
+
if alias in by_stem:
|
|
63
|
+
result[state] = str(by_stem[alias])
|
|
64
|
+
break
|
|
65
|
+
except OSError:
|
|
66
|
+
pass
|
|
67
|
+
return result
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def derive_visual_state(dragging: bool, airborne: bool, surface: str, motion_state: str) -> str:
|
|
71
|
+
"""依目前情形推導應顯示的視覺狀態 / Derive which sprite state to show."""
|
|
72
|
+
if dragging:
|
|
73
|
+
return STATE_DRAG
|
|
74
|
+
if airborne:
|
|
75
|
+
return STATE_FALL
|
|
76
|
+
if surface in (SURFACE_LEFT, SURFACE_RIGHT, SURFACE_CEILING):
|
|
77
|
+
return STATE_CLIMB
|
|
78
|
+
if surface == SURFACE_FLOOR and motion_state == "idle":
|
|
79
|
+
return STATE_IDLE
|
|
80
|
+
return STATE_WALK
|
|
81
|
+
|
|
19
82
|
|
|
20
83
|
class PetMotion:
|
|
21
84
|
"""
|
|
@@ -34,6 +97,8 @@ class PetMotion:
|
|
|
34
97
|
BOUNCE_THRESHOLD = 8.0
|
|
35
98
|
CHASE_STOP_DISTANCE = 10.0
|
|
36
99
|
CHASE_SPEED_FACTOR = 2.0
|
|
100
|
+
CLIMB_CHANCE = 0.5 # chance to grab a wall (vs. turn around) at a floor corner
|
|
101
|
+
DROP_CHANCE = 0.008 # chance per step to let go while on a wall/ceiling
|
|
37
102
|
|
|
38
103
|
def __init__(
|
|
39
104
|
self,
|
|
@@ -45,6 +110,7 @@ class PetMotion:
|
|
|
45
110
|
speed: int = 3,
|
|
46
111
|
behaviour: str = BEHAVIOUR_FLOOR,
|
|
47
112
|
rng=None,
|
|
113
|
+
climb: bool = True,
|
|
48
114
|
) -> None:
|
|
49
115
|
self.x = float(x)
|
|
50
116
|
self.y = float(y)
|
|
@@ -61,6 +127,8 @@ class PetMotion:
|
|
|
61
127
|
self._state_ticks = 0
|
|
62
128
|
self.target: Optional[Tuple[float, float]] = None
|
|
63
129
|
self.asleep = False
|
|
130
|
+
self.climb = bool(climb)
|
|
131
|
+
self.surface = SURFACE_FLOOR
|
|
64
132
|
|
|
65
133
|
@property
|
|
66
134
|
def facing_left(self) -> bool:
|
|
@@ -78,6 +146,7 @@ class PetMotion:
|
|
|
78
146
|
self.vy = float(vy)
|
|
79
147
|
self._airborne = True
|
|
80
148
|
self.asleep = False
|
|
149
|
+
self.surface = SURFACE_FLOOR
|
|
81
150
|
|
|
82
151
|
def step(self) -> Tuple[int, int]:
|
|
83
152
|
left, top, right, bottom = self.bounds
|
|
@@ -88,9 +157,9 @@ class PetMotion:
|
|
|
88
157
|
return self._step_wander(left, top, right, bottom)
|
|
89
158
|
return self._step_floor(left, top, right, bottom, floor_y)
|
|
90
159
|
|
|
91
|
-
# --- floor / gravity ---
|
|
160
|
+
# --- floor / gravity / climbing ---
|
|
92
161
|
def _step_floor(self, left, top, right, bottom, floor_y) -> Tuple[int, int]:
|
|
93
|
-
airborne = self._airborne or self.y < floor_y - 0.5
|
|
162
|
+
airborne = self._airborne or (self.surface == SURFACE_FLOOR and self.y < floor_y - 0.5)
|
|
94
163
|
if airborne:
|
|
95
164
|
self.vy += self.GRAVITY
|
|
96
165
|
self.x += self.vx
|
|
@@ -111,23 +180,81 @@ class PetMotion:
|
|
|
111
180
|
else:
|
|
112
181
|
self.vy = 0.0
|
|
113
182
|
self._airborne = False
|
|
183
|
+
self.surface = SURFACE_FLOOR
|
|
114
184
|
self.vx = float(self.speed) if self.vx >= 0 else float(-self.speed)
|
|
115
185
|
self._new_state(force_walk=True)
|
|
116
186
|
return int(self.x), int(self.y)
|
|
117
187
|
|
|
118
|
-
|
|
188
|
+
if self.surface != SURFACE_FLOOR:
|
|
189
|
+
return self._step_climb(left, top, right, bottom, floor_y)
|
|
190
|
+
|
|
191
|
+
# grounded on the floor: random walk / idle, with a chance to climb a wall
|
|
119
192
|
self.y = float(floor_y)
|
|
120
193
|
if self._state_ticks <= 0:
|
|
121
194
|
self._new_state()
|
|
122
195
|
self._state_ticks -= 1
|
|
123
|
-
if self.state
|
|
196
|
+
if self.state != "walk":
|
|
197
|
+
return int(self.x), int(self.y)
|
|
198
|
+
self.x += self.vx
|
|
199
|
+
if self.x <= left:
|
|
200
|
+
self.x = float(left)
|
|
201
|
+
if self.climb and self._rng.random() < self.CLIMB_CHANCE:
|
|
202
|
+
self.surface = SURFACE_LEFT
|
|
203
|
+
self.vy = float(-self.speed)
|
|
204
|
+
else:
|
|
205
|
+
self.vx = abs(self.vx)
|
|
206
|
+
elif self.x + self.width >= right:
|
|
207
|
+
self.x = float(right - self.width)
|
|
208
|
+
if self.climb and self._rng.random() < self.CLIMB_CHANCE:
|
|
209
|
+
self.surface = SURFACE_RIGHT
|
|
210
|
+
self.vy = float(-self.speed)
|
|
211
|
+
else:
|
|
212
|
+
self.vx = -abs(self.vx)
|
|
213
|
+
return int(self.x), int(self.y)
|
|
214
|
+
|
|
215
|
+
def _step_climb(self, left, top, right, bottom, floor_y) -> Tuple[int, int]:
|
|
216
|
+
"""沿螢幕邊緣爬行;隨機放手則掉落 / Crawl the screen perimeter; may let go and fall."""
|
|
217
|
+
if self._rng.random() < self.DROP_CHANCE:
|
|
218
|
+
self.surface = SURFACE_FLOOR
|
|
219
|
+
self._airborne = True
|
|
220
|
+
self.vy = 1.0
|
|
221
|
+
return int(self.x), int(self.y)
|
|
222
|
+
|
|
223
|
+
if self.surface == SURFACE_RIGHT:
|
|
224
|
+
self.x = float(right - self.width)
|
|
225
|
+
self.y += self.vy
|
|
226
|
+
if self.vy < 0 and self.y <= top: # reached the ceiling, crawl left
|
|
227
|
+
self.y = float(top)
|
|
228
|
+
self.surface = SURFACE_CEILING
|
|
229
|
+
self.vx = float(-self.speed)
|
|
230
|
+
elif self.vy > 0 and self.y >= floor_y: # climbed back down
|
|
231
|
+
self.y = float(floor_y)
|
|
232
|
+
self.surface = SURFACE_FLOOR
|
|
233
|
+
self.vx = float(-self.speed)
|
|
234
|
+
self._new_state(force_walk=True)
|
|
235
|
+
elif self.surface == SURFACE_LEFT:
|
|
236
|
+
self.x = float(left)
|
|
237
|
+
self.y += self.vy
|
|
238
|
+
if self.vy < 0 and self.y <= top:
|
|
239
|
+
self.y = float(top)
|
|
240
|
+
self.surface = SURFACE_CEILING
|
|
241
|
+
self.vx = float(self.speed)
|
|
242
|
+
elif self.vy > 0 and self.y >= floor_y:
|
|
243
|
+
self.y = float(floor_y)
|
|
244
|
+
self.surface = SURFACE_FLOOR
|
|
245
|
+
self.vx = float(self.speed)
|
|
246
|
+
self._new_state(force_walk=True)
|
|
247
|
+
elif self.surface == SURFACE_CEILING:
|
|
248
|
+
self.y = float(top)
|
|
124
249
|
self.x += self.vx
|
|
125
|
-
if self.x <= left:
|
|
250
|
+
if self.vx < 0 and self.x <= left: # corner -> climb down the left wall
|
|
126
251
|
self.x = float(left)
|
|
127
|
-
self.
|
|
128
|
-
|
|
252
|
+
self.surface = SURFACE_LEFT
|
|
253
|
+
self.vy = float(self.speed)
|
|
254
|
+
elif self.vx > 0 and self.x + self.width >= right:
|
|
129
255
|
self.x = float(right - self.width)
|
|
130
|
-
self.
|
|
256
|
+
self.surface = SURFACE_RIGHT
|
|
257
|
+
self.vy = float(self.speed)
|
|
131
258
|
return int(self.x), int(self.y)
|
|
132
259
|
|
|
133
260
|
def _new_state(self, force_walk: bool = False) -> None:
|
|
@@ -187,53 +314,101 @@ class DesktopPetWidget(BaseWidget):
|
|
|
187
314
|
A draggable, throwable, cursor-chasing animated sprite (GIF or image).
|
|
188
315
|
"""
|
|
189
316
|
|
|
317
|
+
clone_requested = Signal()
|
|
318
|
+
|
|
190
319
|
def __init__(self, image_path: str, size: int = 128, speed: int = 3,
|
|
191
|
-
behaviour: str = BEHAVIOUR_FLOOR):
|
|
320
|
+
behaviour: str = BEHAVIOUR_FLOOR, climb: bool = True):
|
|
192
321
|
front_engine_logger.info(
|
|
193
|
-
f"[DesktopPetWidget] Init | path={image_path}, size={size}, speed={speed},
|
|
322
|
+
f"[DesktopPetWidget] Init | path={image_path}, size={size}, speed={speed}, "
|
|
323
|
+
f"behaviour={behaviour}, climb={climb}"
|
|
194
324
|
)
|
|
195
325
|
super().__init__()
|
|
196
326
|
self.opacity = 1.0
|
|
197
327
|
self.pet_size: int = max(16, int(size))
|
|
198
328
|
self.image_path: Path = Path(image_path)
|
|
199
|
-
self.movie: Optional[QMovie] = None
|
|
200
|
-
self.pixmap: Optional[QPixmap] = None
|
|
201
329
|
self._dragging: bool = False
|
|
202
330
|
self._drag_offset = None
|
|
203
331
|
self._last_move_delta: Tuple[int, int] = (0, 0)
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
else:
|
|
213
|
-
front_engine_logger.error(f"[DesktopPetWidget] File not found: {self.image_path}")
|
|
332
|
+
# 視覺狀態 -> ("movie"|"pixmap", 物件) / state -> sprite
|
|
333
|
+
self._sprites: dict = {}
|
|
334
|
+
self._active = None
|
|
335
|
+
self._active_state = None
|
|
336
|
+
|
|
337
|
+
self._load_sprites(self.image_path)
|
|
338
|
+
if not self._sprites:
|
|
339
|
+
front_engine_logger.error(f"[DesktopPetWidget] No sprite found: {self.image_path}")
|
|
214
340
|
message_box = QMessageBox(self)
|
|
215
341
|
message_box.setText(language_wrapper.language_word_dict.get("pet_message_box_text", "Pet image not found"))
|
|
216
342
|
message_box.show()
|
|
217
343
|
|
|
218
344
|
self.resize(self.pet_size, self.pet_size)
|
|
219
|
-
self.motion = PetMotion(
|
|
345
|
+
self.motion = PetMotion(
|
|
346
|
+
0, 0, self.pet_size, self.pet_size, (0, 0, 1920, 1080), speed, behaviour, climb=climb
|
|
347
|
+
)
|
|
348
|
+
self._set_active_sprite(STATE_WALK)
|
|
220
349
|
|
|
221
350
|
self._timer = QTimer(self)
|
|
222
351
|
self._timer.timeout.connect(self._on_tick)
|
|
223
352
|
|
|
353
|
+
self.menu = QMenu(self)
|
|
354
|
+
self.clone_action = QAction(language_wrapper.language_word_dict.get("pet_clone", "Clone"), self)
|
|
355
|
+
self.clone_action.triggered.connect(self.clone_requested.emit)
|
|
356
|
+
self.menu.addAction(self.clone_action)
|
|
224
357
|
self.close_action = QAction(language_wrapper.language_word_dict.get("control_center_close_all", "Close"), self)
|
|
225
358
|
self.close_action.triggered.connect(self.close)
|
|
226
|
-
self.menu = QMenu(self)
|
|
227
359
|
self.menu.addAction(self.close_action)
|
|
228
360
|
|
|
229
361
|
def set_pet_window_flag(self) -> None:
|
|
230
362
|
"""寵物需接收滑鼠以便拖曳,故 allow_input=True 並置頂。"""
|
|
231
363
|
apply_overlay_window_flags(self, show_on_bottom=False, allow_input=True)
|
|
232
364
|
|
|
365
|
+
def _load_sprite(self, path: str):
|
|
366
|
+
if Path(path).suffix.lower() in (".gif", ".webp"):
|
|
367
|
+
movie = QMovie(str(path))
|
|
368
|
+
movie.frameChanged.connect(self.update)
|
|
369
|
+
return ("movie", movie)
|
|
370
|
+
return ("pixmap", QPixmap(str(path)))
|
|
371
|
+
|
|
372
|
+
def _load_sprites(self, image_path: Path) -> None:
|
|
373
|
+
"""單一檔 -> 所有狀態共用;資料夾 -> 依檔名對應各狀態。"""
|
|
374
|
+
if image_path.is_dir():
|
|
375
|
+
for state, path in scan_pet_pack(str(image_path)).items():
|
|
376
|
+
self._sprites[state] = self._load_sprite(path)
|
|
377
|
+
elif image_path.is_file():
|
|
378
|
+
self._sprites["default"] = self._load_sprite(str(image_path))
|
|
379
|
+
|
|
380
|
+
def _sprite_for(self, state: str):
|
|
381
|
+
if "default" in self._sprites:
|
|
382
|
+
return self._sprites["default"]
|
|
383
|
+
if state in self._sprites:
|
|
384
|
+
return self._sprites[state]
|
|
385
|
+
for fallback in (STATE_WALK, STATE_IDLE):
|
|
386
|
+
if fallback in self._sprites:
|
|
387
|
+
return self._sprites[fallback]
|
|
388
|
+
return next(iter(self._sprites.values()), None)
|
|
389
|
+
|
|
390
|
+
def _set_active_sprite(self, state: str) -> None:
|
|
391
|
+
sprite = self._sprite_for(state)
|
|
392
|
+
if sprite is None or sprite is self._active:
|
|
393
|
+
return
|
|
394
|
+
if self._active is not None and self._active[0] == "movie":
|
|
395
|
+
self._active[1].stop()
|
|
396
|
+
self._active = sprite
|
|
397
|
+
self._active_state = state
|
|
398
|
+
if sprite[0] == "movie":
|
|
399
|
+
sprite[1].start()
|
|
400
|
+
self.update()
|
|
401
|
+
|
|
402
|
+
def _visual_state(self) -> str:
|
|
403
|
+
return derive_visual_state(
|
|
404
|
+
self._dragging, self.motion._airborne, self.motion.surface, self.motion.state
|
|
405
|
+
)
|
|
406
|
+
|
|
233
407
|
def _current_pixmap(self) -> Optional[QPixmap]:
|
|
234
|
-
if self.
|
|
235
|
-
return
|
|
236
|
-
|
|
408
|
+
if self._active is None:
|
|
409
|
+
return None
|
|
410
|
+
kind, obj = self._active
|
|
411
|
+
return obj.currentPixmap() if kind == "movie" else obj
|
|
237
412
|
|
|
238
413
|
def draw_content(self, painter: QPainter) -> None:
|
|
239
414
|
pixmap = self._current_pixmap()
|
|
@@ -254,12 +429,14 @@ class DesktopPetWidget(BaseWidget):
|
|
|
254
429
|
|
|
255
430
|
def _on_tick(self) -> None:
|
|
256
431
|
if self._dragging:
|
|
432
|
+
self._set_active_sprite(STATE_DRAG)
|
|
257
433
|
return
|
|
258
434
|
if self.motion.behaviour == BEHAVIOUR_CHASE:
|
|
259
435
|
cursor = QCursor.pos()
|
|
260
436
|
self.motion.set_target(cursor.x(), cursor.y())
|
|
261
437
|
x, y = self.motion.step()
|
|
262
438
|
self.move(x, y)
|
|
439
|
+
self._set_active_sprite(self._visual_state())
|
|
263
440
|
|
|
264
441
|
# --- dragging + throwing ---
|
|
265
442
|
def mousePressEvent(self, event) -> None:
|
|
@@ -267,6 +444,7 @@ class DesktopPetWidget(BaseWidget):
|
|
|
267
444
|
self._dragging = True
|
|
268
445
|
self._last_move_delta = (0, 0)
|
|
269
446
|
self._drag_offset = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
|
|
447
|
+
self._set_active_sprite(STATE_DRAG)
|
|
270
448
|
super().mousePressEvent(event)
|
|
271
449
|
|
|
272
450
|
def mouseMoveEvent(self, event) -> None:
|
|
@@ -292,6 +470,7 @@ class DesktopPetWidget(BaseWidget):
|
|
|
292
470
|
def closeEvent(self, event) -> None:
|
|
293
471
|
if self._timer.isActive():
|
|
294
472
|
self._timer.stop()
|
|
295
|
-
|
|
296
|
-
|
|
473
|
+
for kind, obj in self._sprites.values():
|
|
474
|
+
if kind == "movie":
|
|
475
|
+
obj.stop()
|
|
297
476
|
super().closeEvent(event)
|
|
@@ -2,11 +2,11 @@ from typing import Optional
|
|
|
2
2
|
|
|
3
3
|
from PySide6.QtGui import QGuiApplication
|
|
4
4
|
from PySide6.QtWidgets import (
|
|
5
|
-
QWidget, QGridLayout, QLabel, QPushButton, QMessageBox, QComboBox,
|
|
5
|
+
QWidget, QGridLayout, QLabel, QPushButton, QMessageBox, QComboBox, QCheckBox, QFileDialog,
|
|
6
6
|
)
|
|
7
7
|
|
|
8
8
|
from frontengine.show.pet.desktop_pet import (
|
|
9
|
-
DesktopPetWidget, BEHAVIOUR_FLOOR, BEHAVIOUR_WANDER, BEHAVIOUR_CHASE,
|
|
9
|
+
DesktopPetWidget, BEHAVIOUR_FLOOR, BEHAVIOUR_WANDER, BEHAVIOUR_CHASE, scan_pet_pack,
|
|
10
10
|
)
|
|
11
11
|
from frontengine.ui.dialog.choose_file_dialog import choose_pet
|
|
12
12
|
from frontengine.ui.page.utils import (
|
|
@@ -38,6 +38,10 @@ class PetSettingUI(QWidget):
|
|
|
38
38
|
language_wrapper.language_word_dict.get("pet_choose_file", "Choose pet sprite")
|
|
39
39
|
)
|
|
40
40
|
self.choose_file_button.clicked.connect(self.choose_and_play)
|
|
41
|
+
self.choose_pack_button = QPushButton(
|
|
42
|
+
language_wrapper.language_word_dict.get("pet_choose_pack", "Choose pet pack...")
|
|
43
|
+
)
|
|
44
|
+
self.choose_pack_button.clicked.connect(self.choose_pack)
|
|
41
45
|
self.ready_label = QLabel(language_wrapper.language_word_dict.get("Not Ready"))
|
|
42
46
|
|
|
43
47
|
# Size
|
|
@@ -62,6 +66,10 @@ class PetSettingUI(QWidget):
|
|
|
62
66
|
self.behaviour_combobox.addItem(
|
|
63
67
|
language_wrapper.language_word_dict.get("pet_behaviour_chase", "Chase cursor"), BEHAVIOUR_CHASE)
|
|
64
68
|
|
|
69
|
+
# Climb walls / ceiling (only meaningful in floor mode)
|
|
70
|
+
self.climb_checkbox = QCheckBox(language_wrapper.language_word_dict.get("pet_climb_label", "Climb walls"))
|
|
71
|
+
self.climb_checkbox.setChecked(True)
|
|
72
|
+
|
|
65
73
|
# Start
|
|
66
74
|
self.start_button = QPushButton(language_wrapper.language_word_dict.get("pet_start", "Spawn pet"))
|
|
67
75
|
self.start_button.clicked.connect(self.start_play_pet)
|
|
@@ -77,26 +85,37 @@ class PetSettingUI(QWidget):
|
|
|
77
85
|
# Layout
|
|
78
86
|
self.grid_layout.addWidget(self.choose_file_button, 0, 0)
|
|
79
87
|
self.grid_layout.addWidget(self.ready_label, 0, 1)
|
|
88
|
+
self.grid_layout.addWidget(self.choose_pack_button, 0, 2)
|
|
80
89
|
self.grid_layout.addWidget(self.size_label, 1, 0)
|
|
81
90
|
self.grid_layout.addWidget(self.size_combobox, 1, 1)
|
|
82
91
|
self.grid_layout.addWidget(self.speed_label, 2, 0)
|
|
83
92
|
self.grid_layout.addWidget(self.speed_combobox, 2, 1)
|
|
84
93
|
self.grid_layout.addWidget(self.behaviour_label, 3, 0)
|
|
85
94
|
self.grid_layout.addWidget(self.behaviour_combobox, 3, 1)
|
|
95
|
+
self.grid_layout.addWidget(self.climb_checkbox, 3, 2)
|
|
86
96
|
self.grid_layout.addWidget(self.start_button, 4, 0)
|
|
87
97
|
self.grid_layout.addWidget(self.recent_files_label, 5, 0)
|
|
88
98
|
self.grid_layout.addWidget(self.recent_files_combobox, 5, 1)
|
|
89
99
|
|
|
90
|
-
def
|
|
100
|
+
def _spawn_pet(self) -> None:
|
|
101
|
+
"""建立、顯示並開始移動一隻寵物(供 Start 與右鍵複製共用)。"""
|
|
102
|
+
if not self.pet_image_path:
|
|
103
|
+
return
|
|
91
104
|
pet = DesktopPetWidget(
|
|
92
105
|
image_path=self.pet_image_path,
|
|
93
106
|
size=int(self.size_combobox.currentText()),
|
|
94
107
|
speed=int(self.speed_combobox.currentText()),
|
|
95
108
|
behaviour=self.behaviour_combobox.currentData(),
|
|
109
|
+
climb=self.climb_checkbox.isChecked(),
|
|
96
110
|
)
|
|
111
|
+
pet.clone_requested.connect(self._spawn_pet)
|
|
97
112
|
pet.set_pet_window_flag()
|
|
98
113
|
self.pet_list.append(pet)
|
|
99
|
-
|
|
114
|
+
screen = QGuiApplication.primaryScreen()
|
|
115
|
+
geometry = screen.availableGeometry() if screen is not None else None
|
|
116
|
+
pet.show()
|
|
117
|
+
if geometry is not None:
|
|
118
|
+
pet.start_moving((geometry.left(), geometry.top(), geometry.right(), geometry.bottom()))
|
|
100
119
|
|
|
101
120
|
def start_play_pet(self) -> None:
|
|
102
121
|
front_engine_logger.info("[PetSettingUI] start_play_pet")
|
|
@@ -105,13 +124,7 @@ class PetSettingUI(QWidget):
|
|
|
105
124
|
message_box.setText(language_wrapper.language_word_dict.get("not_prepare"))
|
|
106
125
|
message_box.exec()
|
|
107
126
|
return
|
|
108
|
-
|
|
109
|
-
screen = QGuiApplication.primaryScreen()
|
|
110
|
-
geometry = screen.availableGeometry() if screen is not None else None
|
|
111
|
-
pet.show()
|
|
112
|
-
if geometry is not None:
|
|
113
|
-
bounds = (geometry.left(), geometry.top(), geometry.right(), geometry.bottom())
|
|
114
|
-
pet.start_moving(bounds)
|
|
127
|
+
self._spawn_pet()
|
|
115
128
|
|
|
116
129
|
def choose_and_play(self) -> None:
|
|
117
130
|
front_engine_logger.info("[PetSettingUI] choose_and_play")
|
|
@@ -124,6 +137,28 @@ class PetSettingUI(QWidget):
|
|
|
124
137
|
add_recent_file("pet", self.pet_image_path)
|
|
125
138
|
reload_recent_combobox(self.recent_files_combobox, "pet")
|
|
126
139
|
|
|
140
|
+
def choose_pack(self) -> None:
|
|
141
|
+
"""選擇動作包資料夾(依 walk/idle/climb/fall/drag 檔名對應狀態)。"""
|
|
142
|
+
front_engine_logger.info("[PetSettingUI] choose_pack")
|
|
143
|
+
folder = QFileDialog.getExistingDirectory(
|
|
144
|
+
self, language_wrapper.language_word_dict.get("pet_choose_pack", "Choose pet pack...")
|
|
145
|
+
)
|
|
146
|
+
if not folder:
|
|
147
|
+
return
|
|
148
|
+
if not scan_pet_pack(folder):
|
|
149
|
+
QMessageBox.warning(
|
|
150
|
+
self,
|
|
151
|
+
language_wrapper.language_word_dict.get("pet_choose_pack", "Choose pet pack..."),
|
|
152
|
+
language_wrapper.language_word_dict.get(
|
|
153
|
+
"pet_pack_empty", "No sprites (walk/idle/climb/fall/drag) found in that folder."),
|
|
154
|
+
)
|
|
155
|
+
return
|
|
156
|
+
self.pet_image_path = folder
|
|
157
|
+
self.ready_to_play = True
|
|
158
|
+
self.ready_label.setText(language_wrapper.language_word_dict.get("Ready"))
|
|
159
|
+
add_recent_file("pet", folder)
|
|
160
|
+
reload_recent_combobox(self.recent_files_combobox, "pet")
|
|
161
|
+
|
|
127
162
|
def _apply_recent_file(self, _index: int = 0) -> None:
|
|
128
163
|
path = self.recent_files_combobox.currentData()
|
|
129
164
|
self.recent_files_combobox.setCurrentIndex(0)
|
|
@@ -147,6 +182,7 @@ class PetSettingUI(QWidget):
|
|
|
147
182
|
"size": self.size_combobox.currentText(),
|
|
148
183
|
"speed": self.speed_combobox.currentText(),
|
|
149
184
|
"behaviour": self.behaviour_combobox.currentData(),
|
|
185
|
+
"climb": self.climb_checkbox.isChecked(),
|
|
150
186
|
}
|
|
151
187
|
|
|
152
188
|
def set_state(self, state: dict) -> None:
|
|
@@ -166,3 +202,5 @@ class PetSettingUI(QWidget):
|
|
|
166
202
|
index = self.behaviour_combobox.findData(behaviour)
|
|
167
203
|
if index >= 0:
|
|
168
204
|
self.behaviour_combobox.setCurrentIndex(index)
|
|
205
|
+
if "climb" in state:
|
|
206
|
+
self.climb_checkbox.setChecked(bool(state["climb"]))
|
|
@@ -223,6 +223,10 @@ english_word_dict = {
|
|
|
223
223
|
"pet_behaviour_floor": "Walk on floor",
|
|
224
224
|
"pet_behaviour_wander": "Free wander",
|
|
225
225
|
"pet_behaviour_chase": "Chase cursor",
|
|
226
|
+
"pet_climb_label": "Climb walls",
|
|
227
|
+
"pet_clone": "Clone",
|
|
228
|
+
"pet_choose_pack": "Choose pet pack...",
|
|
229
|
+
"pet_pack_empty": "No sprites (walk/idle/climb/fall/drag) found in that folder.",
|
|
226
230
|
"pet_start": "Spawn pet",
|
|
227
231
|
"pet_message_box_text": "Pet image not found",
|
|
228
232
|
}
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/traditional_chinese.py
RENAMED
|
@@ -224,6 +224,10 @@ traditional_chinese_word_dict = {
|
|
|
224
224
|
"pet_behaviour_floor": "沿底部行走",
|
|
225
225
|
"pet_behaviour_wander": "自由漫遊",
|
|
226
226
|
"pet_behaviour_chase": "追逐游標",
|
|
227
|
+
"pet_climb_label": "攀爬牆壁",
|
|
228
|
+
"pet_clone": "複製",
|
|
229
|
+
"pet_choose_pack": "選擇動作包資料夾...",
|
|
230
|
+
"pet_pack_empty": "該資料夾找不到精靈檔(walk/idle/climb/fall/drag)。",
|
|
227
231
|
"pet_start": "召喚寵物",
|
|
228
232
|
"pet_message_box_text": "找不到寵物圖片",
|
|
229
233
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frontengine
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.5
|
|
4
4
|
Summary: FrontEngine is use-define frontview or only use like screen saver
|
|
5
5
|
Author-email: JE-Chen <jechenmailman@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/Intergration-Automation-Testing/FrontEngine
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/control_center/control_center_ui.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/image.py
RENAMED
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/registry.py
RENAMED
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/sound.py
RENAMED
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/text.py
RENAMED
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_page/video.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/scene_setting/scene_setting_ui.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/ui/page/sound_player/sound_player_setting_ui.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/critical_exit/check_key_is_press.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/language_wrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/multi_language/simplified_chinese.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/preset_schedule/preset_schedule_service.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/redirect_manager/redirect_manager_class.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/smart_pause/smart_pause_service.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.3 → frontengine-1.0.5}/frontengine/utils/theme_schedule/theme_schedule_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|