frontengine 1.0.20__tar.gz → 1.0.22__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.20 → frontengine-1.0.22}/PKG-INFO +1 -1
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/pet/desktop_pet.py +83 -2
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/pet/pet_setting_ui.py +43 -3
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/user_setting/user_setting_file.py +3 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/multi_language/english.py +1 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/multi_language/traditional_chinese.py +1 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine.egg-info/PKG-INFO +1 -1
- {frontengine-1.0.20 → frontengine-1.0.22}/pyproject.toml +1 -1
- {frontengine-1.0.20 → frontengine-1.0.22}/LICENSE +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/README.md +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/__main__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/base_widget.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/gif/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/gif/paint_gif.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/image/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/image/paint_image.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/load/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/load/load_someone_make_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/overlay_factory.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/particle/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/particle/particle_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/pet/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/scene/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/scene/extend_graphic_scene.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/scene/extend_graphic_view.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/scene/scene.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/sound_player/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/sound_player/sound_effect.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/sound_player/sound_player.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/text/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/text/draw_text.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/video/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/video/video_player.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/web/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/web/webview.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/show/window_helpers.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/system_tray/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/system_tray/extend_system_tray.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/color/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/color/global_color.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/dialog/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/dialog/choose_file_dialog.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/dialog/hotkey_settings_dialog.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/dialog/save_file_dialog.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/main_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/menu/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/menu/help_menu.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/menu/how_to_menu.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/menu/language_menu.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/menu/preset_menu.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/menu/settings_menu.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/control_center/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/control_center/control_center_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/gif/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/gif/gif_setting_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/image/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/image/image_setting_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/particle/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/particle/particle_setting_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/pet/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_manager.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/gif.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/image.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/registry.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/sound.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/text.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/video.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/web.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_setting_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/sound_player/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/sound_player/sound_player_setting_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/text/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/text/text_setting_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/utils.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/video/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/video/video_setting_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/web/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/web/web_setting_ui.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/user_setting/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/user_setting/preset_repository.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/user_setting/scene_setting.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/browser/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/browser/browser.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/critical_exit/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/critical_exit/check_key_is_press.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/critical_exit/critical_exit.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/critical_exit/win32_vk.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/exception/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/exception/exception_tags.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/exception/exceptions.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/file/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/file/open/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/file/open/open_file.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/file/save/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/file/save/save_file.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/hotkey/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/hotkey/hotkey_service.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/json/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/json/json_file.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/json/json_repository.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/json_format/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/json_format/json_process.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/logging/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/logging/loggin_instance.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/multi_language/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/multi_language/france.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/multi_language/germany.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/multi_language/italy.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/multi_language/language_wrapper.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/multi_language/russian.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/multi_language/simplified_chinese.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/preset_schedule/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/preset_schedule/preset_schedule_service.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/redirect_manager/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/redirect_manager/redirect_manager_class.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/smart_pause/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/smart_pause/smart_pause_service.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/theme_schedule/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/theme_schedule/theme_schedule_service.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/web_url.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/worker/__init__.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine/worker/qthread_worker.py +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine.egg-info/SOURCES.txt +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine.egg-info/dependency_links.txt +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine.egg-info/entry_points.txt +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine.egg-info/requires.txt +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/frontengine.egg-info/top_level.txt +0 -0
- {frontengine-1.0.20 → frontengine-1.0.22}/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.22
|
|
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
|
|
@@ -168,6 +168,46 @@ def idle_seconds():
|
|
|
168
168
|
return None
|
|
169
169
|
|
|
170
170
|
|
|
171
|
+
class PetTimeline:
|
|
172
|
+
"""
|
|
173
|
+
寵物動作時間軸:一連串 (offset_seconds, action_dict),依經過秒數依序觸發。
|
|
174
|
+
A scene-timeline of (offset_seconds, action_dict) events fired in order as
|
|
175
|
+
elapsed time passes. Events are sorted; pop_due advances an internal index.
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
def __init__(self, events) -> None:
|
|
179
|
+
self._events = sorted(list(events), key=lambda item: item[0])
|
|
180
|
+
self._index = 0
|
|
181
|
+
|
|
182
|
+
def __len__(self) -> int:
|
|
183
|
+
return len(self._events)
|
|
184
|
+
|
|
185
|
+
def reset(self) -> None:
|
|
186
|
+
self._index = 0
|
|
187
|
+
|
|
188
|
+
def pop_due(self, elapsed: float) -> list:
|
|
189
|
+
due = []
|
|
190
|
+
while self._index < len(self._events) and self._events[self._index][0] <= elapsed:
|
|
191
|
+
due.append(self._events[self._index][1])
|
|
192
|
+
self._index += 1
|
|
193
|
+
return due
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def parse_timeline(raw) -> list:
|
|
197
|
+
"""把設定裡的 [{'at': 秒, ...}] 轉成 (offset, action_dict) 清單,忽略格式錯誤者。"""
|
|
198
|
+
events = []
|
|
199
|
+
if isinstance(raw, list):
|
|
200
|
+
for item in raw:
|
|
201
|
+
if not isinstance(item, dict) or "at" not in item:
|
|
202
|
+
continue
|
|
203
|
+
try:
|
|
204
|
+
offset = float(item["at"])
|
|
205
|
+
except (TypeError, ValueError):
|
|
206
|
+
continue
|
|
207
|
+
events.append((offset, item))
|
|
208
|
+
return events
|
|
209
|
+
|
|
210
|
+
|
|
171
211
|
def pop_due_reminders(now, reminders):
|
|
172
212
|
"""
|
|
173
213
|
依 now 分出已到期與未到期的提醒。reminders 為 (due_datetime, text) 清單。
|
|
@@ -797,7 +837,8 @@ class DesktopPetWidget(BaseWidget):
|
|
|
797
837
|
|
|
798
838
|
def __init__(self, image_path: str, size: int = 128, speed: int = 3,
|
|
799
839
|
behaviour: str = BEHAVIOUR_FLOOR, climb: bool = True, talk: bool = True,
|
|
800
|
-
sound_path: Optional[str] = None, sit_on_windows: bool = True
|
|
840
|
+
sound_path: Optional[str] = None, sit_on_windows: bool = True,
|
|
841
|
+
volume: float = 1.0):
|
|
801
842
|
front_engine_logger.info(
|
|
802
843
|
f"[DesktopPetWidget] Init | path={image_path}, size={size}, speed={speed}, "
|
|
803
844
|
f"behaviour={behaviour}, climb={climb}, talk={talk}, sound={sound_path}, "
|
|
@@ -842,6 +883,7 @@ class DesktopPetWidget(BaseWidget):
|
|
|
842
883
|
self._hunger = PetHunger(user_setting_dict.get("pet_hunger", 70))
|
|
843
884
|
self._hunger_warned = False
|
|
844
885
|
self._messages = self._load_messages()
|
|
886
|
+
self._volume = max(0.0, min(1.0, float(volume)))
|
|
845
887
|
self._sound: Optional[QSoundEffect] = None
|
|
846
888
|
self._init_sound(sound_path)
|
|
847
889
|
self._sit_on_windows = bool(sit_on_windows)
|
|
@@ -860,7 +902,10 @@ class DesktopPetWidget(BaseWidget):
|
|
|
860
902
|
self._now_provider = datetime.now
|
|
861
903
|
self._reminders: list = []
|
|
862
904
|
self._reminder_timer = QTimer(self)
|
|
863
|
-
self._reminder_timer.timeout.connect(self.
|
|
905
|
+
self._reminder_timer.timeout.connect(self._on_schedule_tick)
|
|
906
|
+
# 場景時間軸 / Scene timeline of scheduled actions
|
|
907
|
+
self._timeline = PetTimeline(parse_timeline(user_setting_dict.get("pet_timeline", [])))
|
|
908
|
+
self._timeline_start = None
|
|
864
909
|
self._bubble = SpeechBubble()
|
|
865
910
|
self._chatter_timer = QTimer(self)
|
|
866
911
|
self._chatter_timer.setSingleShot(True)
|
|
@@ -999,6 +1044,8 @@ class DesktopPetWidget(BaseWidget):
|
|
|
999
1044
|
self._timer.start(max(10, int(interval_ms)))
|
|
1000
1045
|
self._schedule_chatter()
|
|
1001
1046
|
self._reminder_timer.start(10000)
|
|
1047
|
+
if self._timeline_start is None:
|
|
1048
|
+
self._timeline_start = self._now_provider()
|
|
1002
1049
|
|
|
1003
1050
|
def _load_messages(self) -> dict:
|
|
1004
1051
|
d = language_wrapper.language_word_dict
|
|
@@ -1067,6 +1114,39 @@ class DesktopPetWidget(BaseWidget):
|
|
|
1067
1114
|
self._reminders.append((due, str(text)))
|
|
1068
1115
|
front_engine_logger.info(f"[DesktopPetWidget] reminder set | due={due}, text={text}")
|
|
1069
1116
|
|
|
1117
|
+
def _on_schedule_tick(self) -> None:
|
|
1118
|
+
self._check_reminders()
|
|
1119
|
+
self._check_timeline()
|
|
1120
|
+
|
|
1121
|
+
def set_timeline(self, raw) -> None:
|
|
1122
|
+
"""設定場景時間軸並從現在起算 / Set the timeline and start its clock now."""
|
|
1123
|
+
self._timeline = PetTimeline(parse_timeline(raw))
|
|
1124
|
+
self._timeline_start = self._now_provider()
|
|
1125
|
+
|
|
1126
|
+
def _check_timeline(self) -> None:
|
|
1127
|
+
if self._timeline is None or self._timeline_start is None or len(self._timeline) == 0:
|
|
1128
|
+
return
|
|
1129
|
+
elapsed = (self._now_provider() - self._timeline_start).total_seconds()
|
|
1130
|
+
for action in self._timeline.pop_due(elapsed):
|
|
1131
|
+
self._run_timeline_action(action)
|
|
1132
|
+
|
|
1133
|
+
def _run_timeline_action(self, action) -> None:
|
|
1134
|
+
if not isinstance(action, dict):
|
|
1135
|
+
return
|
|
1136
|
+
if action.get("say"):
|
|
1137
|
+
self.say(str(action["say"]))
|
|
1138
|
+
if action.get("sleep"):
|
|
1139
|
+
self.motion.sleep()
|
|
1140
|
+
if action.get("wake"):
|
|
1141
|
+
self.motion.wake()
|
|
1142
|
+
if action.get("feed"):
|
|
1143
|
+
self.feed()
|
|
1144
|
+
if action.get("status"):
|
|
1145
|
+
self.show_status()
|
|
1146
|
+
behaviour = action.get("behaviour")
|
|
1147
|
+
if behaviour in (BEHAVIOUR_FLOOR, BEHAVIOUR_WANDER, BEHAVIOUR_CHASE):
|
|
1148
|
+
self.motion.behaviour = behaviour
|
|
1149
|
+
|
|
1070
1150
|
def _check_reminders(self) -> None:
|
|
1071
1151
|
if not self._reminders:
|
|
1072
1152
|
return
|
|
@@ -1101,6 +1181,7 @@ class DesktopPetWidget(BaseWidget):
|
|
|
1101
1181
|
try:
|
|
1102
1182
|
self._sound = QSoundEffect(self)
|
|
1103
1183
|
self._sound.setSource(QUrl.fromLocalFile(str(path)))
|
|
1184
|
+
self._sound.setVolume(self._volume)
|
|
1104
1185
|
except Exception as error: # pragma: no cover - audio backend guard
|
|
1105
1186
|
front_engine_logger.warning(f"[DesktopPetWidget] sound load failed: {error!r}")
|
|
1106
1187
|
self._sound = None
|
|
@@ -11,8 +11,10 @@ from frontengine.show.pet.desktop_pet import (
|
|
|
11
11
|
from frontengine.ui.dialog.choose_file_dialog import choose_pet, choose_wav_sound
|
|
12
12
|
from frontengine.ui.page.utils import (
|
|
13
13
|
build_recent_combobox,
|
|
14
|
+
build_target_monitor_combobox,
|
|
14
15
|
enable_file_drop,
|
|
15
16
|
reload_recent_combobox,
|
|
17
|
+
resolve_preferred_monitor,
|
|
16
18
|
)
|
|
17
19
|
from frontengine.user_setting.user_setting_file import add_recent_file
|
|
18
20
|
from frontengine.utils.logging.loggin_instance import front_engine_logger
|
|
@@ -79,6 +81,16 @@ class PetSettingUI(QWidget):
|
|
|
79
81
|
self.sit_checkbox = QCheckBox(language_wrapper.language_word_dict.get("pet_sit_label", "Sit on windows"))
|
|
80
82
|
self.sit_checkbox.setChecked(True)
|
|
81
83
|
|
|
84
|
+
# Target monitor + sound volume
|
|
85
|
+
self.target_monitor_label = QLabel(
|
|
86
|
+
language_wrapper.language_word_dict.get("target_monitor_label", "Target monitor"))
|
|
87
|
+
self.target_monitor_combobox = build_target_monitor_combobox()
|
|
88
|
+
self.volume_label = QLabel(language_wrapper.language_word_dict.get("pet_volume_label", "Volume"))
|
|
89
|
+
self.volume_combobox = QComboBox()
|
|
90
|
+
for label, value in (("0%", 0), ("25%", 25), ("50%", 50), ("75%", 75), ("100%", 100)):
|
|
91
|
+
self.volume_combobox.addItem(label, value)
|
|
92
|
+
self.volume_combobox.setCurrentText("100%")
|
|
93
|
+
|
|
82
94
|
# Start
|
|
83
95
|
self.start_button = QPushButton(language_wrapper.language_word_dict.get("pet_start", "Spawn pet"))
|
|
84
96
|
self.start_button.clicked.connect(self.start_play_pet)
|
|
@@ -108,6 +120,10 @@ class PetSettingUI(QWidget):
|
|
|
108
120
|
self.grid_layout.addWidget(self.start_button, 4, 0)
|
|
109
121
|
self.grid_layout.addWidget(self.recent_files_label, 5, 0)
|
|
110
122
|
self.grid_layout.addWidget(self.recent_files_combobox, 5, 1)
|
|
123
|
+
self.grid_layout.addWidget(self.target_monitor_label, 6, 0)
|
|
124
|
+
self.grid_layout.addWidget(self.target_monitor_combobox, 6, 1)
|
|
125
|
+
self.grid_layout.addWidget(self.volume_label, 6, 2)
|
|
126
|
+
self.grid_layout.addWidget(self.volume_combobox, 7, 2)
|
|
111
127
|
|
|
112
128
|
def _spawn_pet(self) -> None:
|
|
113
129
|
"""建立、顯示並開始移動一隻寵物(供 Start 與右鍵複製共用)。"""
|
|
@@ -122,16 +138,30 @@ class PetSettingUI(QWidget):
|
|
|
122
138
|
talk=self.talk_checkbox.isChecked(),
|
|
123
139
|
sound_path=self.pet_sound_path,
|
|
124
140
|
sit_on_windows=self.sit_checkbox.isChecked(),
|
|
141
|
+
volume=int(self.volume_combobox.currentData()) / 100.0,
|
|
125
142
|
)
|
|
126
143
|
pet.clone_requested.connect(self._spawn_pet)
|
|
127
144
|
pet.set_peers_provider(lambda me=pet: self._peer_centers(me))
|
|
128
145
|
pet.set_pet_window_flag()
|
|
129
146
|
self.pet_list.append(pet)
|
|
130
|
-
screen = QGuiApplication.primaryScreen()
|
|
131
|
-
geometry = screen.availableGeometry() if screen is not None else None
|
|
132
147
|
pet.show()
|
|
148
|
+
geometry = self._target_geometry()
|
|
133
149
|
if geometry is not None:
|
|
134
|
-
pet.
|
|
150
|
+
pet.setScreen(geometry[1])
|
|
151
|
+
bounds = geometry[0]
|
|
152
|
+
pet.start_moving((bounds.left(), bounds.top(), bounds.right(), bounds.bottom()))
|
|
153
|
+
|
|
154
|
+
def _target_geometry(self):
|
|
155
|
+
"""回傳 (available_geometry, screen) 依所選目標螢幕,否則主螢幕。"""
|
|
156
|
+
screens = QGuiApplication.screens()
|
|
157
|
+
index = resolve_preferred_monitor(self.target_monitor_combobox)
|
|
158
|
+
if index is not None and 0 <= index < len(screens):
|
|
159
|
+
screen = screens[index]
|
|
160
|
+
else:
|
|
161
|
+
screen = QGuiApplication.primaryScreen()
|
|
162
|
+
if screen is None:
|
|
163
|
+
return None
|
|
164
|
+
return (screen.availableGeometry(), screen)
|
|
135
165
|
|
|
136
166
|
def _peer_centers(self, me) -> list:
|
|
137
167
|
"""回傳其他仍存活寵物的中心座標(略過已被銷毀者)。"""
|
|
@@ -221,6 +251,8 @@ class PetSettingUI(QWidget):
|
|
|
221
251
|
"talk": self.talk_checkbox.isChecked(),
|
|
222
252
|
"sound": self.pet_sound_path,
|
|
223
253
|
"sit": self.sit_checkbox.isChecked(),
|
|
254
|
+
"target_monitor": self.target_monitor_combobox.currentText(),
|
|
255
|
+
"volume": self.volume_combobox.currentText(),
|
|
224
256
|
}
|
|
225
257
|
|
|
226
258
|
def set_state(self, state: dict) -> None:
|
|
@@ -248,3 +280,11 @@ class PetSettingUI(QWidget):
|
|
|
248
280
|
self.pet_sound_path = str(state["sound"])
|
|
249
281
|
if "sit" in state:
|
|
250
282
|
self.sit_checkbox.setChecked(bool(state["sit"]))
|
|
283
|
+
if state.get("target_monitor") is not None:
|
|
284
|
+
index = self.target_monitor_combobox.findText(str(state["target_monitor"]))
|
|
285
|
+
if index >= 0:
|
|
286
|
+
self.target_monitor_combobox.setCurrentIndex(index)
|
|
287
|
+
if state.get("volume") is not None:
|
|
288
|
+
index = self.volume_combobox.findText(str(state["volume"]))
|
|
289
|
+
if index >= 0:
|
|
290
|
+
self.volume_combobox.setCurrentIndex(index)
|
|
@@ -42,6 +42,9 @@ user_setting_dict: Dict[str, Any] = {
|
|
|
42
42
|
# 桌面寵物親密度(累積互動)
|
|
43
43
|
# Desktop pet affection (accumulated interactions)
|
|
44
44
|
"pet_affection": 0,
|
|
45
|
+
# 桌面寵物場景時間軸:[{"at": 秒, "say"/"sleep"/"feed"/"behaviour": ...}, ...]
|
|
46
|
+
# Desktop pet scene timeline of scheduled actions
|
|
47
|
+
"pet_timeline": [],
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
|
|
@@ -246,6 +246,7 @@ english_word_dict = {
|
|
|
246
246
|
"pet_pack_empty": "No sprites (walk/idle/sleep/climb/fall/drag) found in that folder.",
|
|
247
247
|
"pet_talk_label": "Speech bubbles",
|
|
248
248
|
"pet_sit_label": "Sit on windows",
|
|
249
|
+
"pet_volume_label": "Volume",
|
|
249
250
|
"pet_chatter_morning": "Good morning!|Rise and shine!|Ready for the day?",
|
|
250
251
|
"pet_chatter_afternoon": "Good afternoon!|Taking a break?|Keep it up!",
|
|
251
252
|
"pet_chatter_evening": "Good evening!|How was your day?|Almost done?",
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/multi_language/traditional_chinese.py
RENAMED
|
@@ -247,6 +247,7 @@ traditional_chinese_word_dict = {
|
|
|
247
247
|
"pet_pack_empty": "該資料夾找不到精靈檔(walk/idle/sleep/climb/fall/drag)。",
|
|
248
248
|
"pet_talk_label": "對話泡泡",
|
|
249
249
|
"pet_sit_label": "站在視窗上",
|
|
250
|
+
"pet_volume_label": "音量",
|
|
250
251
|
"pet_chatter_morning": "早安!|新的一天開始囉!|準備好了嗎?",
|
|
251
252
|
"pet_chatter_afternoon": "午安!|要不要休息一下?|繼續加油!",
|
|
252
253
|
"pet_chatter_evening": "晚上好!|今天過得如何?|快完成了嗎?",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frontengine
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.22
|
|
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.20 → frontengine-1.0.22}/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
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/particle/particle_setting_ui.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_manager.py
RENAMED
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/gif.py
RENAMED
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/image.py
RENAMED
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/registry.py
RENAMED
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/sound.py
RENAMED
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/text.py
RENAMED
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/video.py
RENAMED
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_page/web.py
RENAMED
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/ui/page/scene_setting/scene_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
|
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/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.20 → frontengine-1.0.22}/frontengine/utils/multi_language/language_wrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/multi_language/simplified_chinese.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/frontengine/utils/smart_pause/smart_pause_service.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.20 → frontengine-1.0.22}/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
|