frontengine 1.0.9__tar.gz → 1.0.10__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.9 → frontengine-1.0.10}/PKG-INFO +1 -1
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/pet/desktop_pet.py +156 -29
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/pet/pet_setting_ui.py +7 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/multi_language/english.py +1 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/multi_language/traditional_chinese.py +1 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine.egg-info/PKG-INFO +1 -1
- {frontengine-1.0.9 → frontengine-1.0.10}/pyproject.toml +1 -1
- {frontengine-1.0.9 → frontengine-1.0.10}/LICENSE +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/README.md +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/__main__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/base_widget.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/gif/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/gif/paint_gif.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/image/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/image/paint_image.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/load/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/load/load_someone_make_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/overlay_factory.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/particle/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/particle/particle_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/pet/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/scene/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/scene/extend_graphic_scene.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/scene/extend_graphic_view.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/scene/scene.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/sound_player/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/sound_player/sound_effect.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/sound_player/sound_player.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/text/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/text/draw_text.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/video/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/video/video_player.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/web/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/web/webview.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/show/window_helpers.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/system_tray/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/system_tray/extend_system_tray.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/color/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/color/global_color.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/dialog/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/dialog/choose_file_dialog.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/dialog/hotkey_settings_dialog.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/dialog/save_file_dialog.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/main_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/menu/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/menu/help_menu.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/menu/how_to_menu.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/menu/language_menu.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/menu/preset_menu.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/menu/settings_menu.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/control_center/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/control_center/control_center_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/gif/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/gif/gif_setting_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/image/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/image/image_setting_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/particle/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/particle/particle_setting_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/pet/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_manager.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/gif.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/image.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/registry.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/sound.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/text.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/video.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/web.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_setting_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/sound_player/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/sound_player/sound_player_setting_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/text/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/text/text_setting_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/utils.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/video/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/video/video_setting_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/web/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/web/web_setting_ui.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/user_setting/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/user_setting/preset_repository.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/user_setting/scene_setting.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/user_setting/user_setting_file.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/browser/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/browser/browser.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/critical_exit/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/critical_exit/check_key_is_press.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/critical_exit/critical_exit.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/critical_exit/win32_vk.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/exception/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/exception/exception_tags.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/exception/exceptions.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/file/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/file/open/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/file/open/open_file.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/file/save/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/file/save/save_file.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/hotkey/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/hotkey/hotkey_service.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/json/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/json/json_file.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/json/json_repository.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/json_format/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/json_format/json_process.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/logging/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/logging/loggin_instance.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/multi_language/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/multi_language/france.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/multi_language/germany.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/multi_language/italy.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/multi_language/language_wrapper.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/multi_language/russian.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/multi_language/simplified_chinese.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/preset_schedule/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/preset_schedule/preset_schedule_service.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/redirect_manager/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/redirect_manager/redirect_manager_class.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/smart_pause/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/smart_pause/smart_pause_service.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/theme_schedule/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/theme_schedule/theme_schedule_service.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/web_url.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/worker/__init__.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine/worker/qthread_worker.py +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine.egg-info/SOURCES.txt +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine.egg-info/dependency_links.txt +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine.egg-info/entry_points.txt +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine.egg-info/requires.txt +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/frontengine.egg-info/top_level.txt +0 -0
- {frontengine-1.0.9 → frontengine-1.0.10}/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.10
|
|
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
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import random as _random_module
|
|
2
|
+
import sys
|
|
2
3
|
from datetime import datetime
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import Optional, Tuple
|
|
@@ -96,6 +97,53 @@ def derive_visual_state(dragging: bool, airborne: bool, surface: str, motion_sta
|
|
|
96
97
|
return STATE_WALK
|
|
97
98
|
|
|
98
99
|
|
|
100
|
+
# 列舉可站立視窗時要略過的外殼視窗類別
|
|
101
|
+
# Shell window classes skipped when enumerating standable windows.
|
|
102
|
+
_PLATFORM_SKIP_CLASSES = {"WorkerW", "Progman", "Shell_TrayWnd", "Button"}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def windows_platforms(exclude_hwnds=()) -> list:
|
|
106
|
+
"""
|
|
107
|
+
回傳目前可見頂層視窗的上緣做為可站立平台 (left, right, top_y)。僅 Windows
|
|
108
|
+
有效,其餘平台或發生錯誤時回傳空清單。
|
|
109
|
+
Return the top edges of visible top-level windows as standable platforms
|
|
110
|
+
(left, right, top_y). Windows only; returns [] elsewhere or on error.
|
|
111
|
+
"""
|
|
112
|
+
if sys.platform != "win32":
|
|
113
|
+
return []
|
|
114
|
+
try:
|
|
115
|
+
import ctypes
|
|
116
|
+
from ctypes import wintypes
|
|
117
|
+
|
|
118
|
+
user32 = ctypes.windll.user32
|
|
119
|
+
exclude = {int(h) for h in exclude_hwnds}
|
|
120
|
+
platforms: list = []
|
|
121
|
+
|
|
122
|
+
@ctypes.WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintypes.LPARAM)
|
|
123
|
+
def _collect(hwnd, _lparam):
|
|
124
|
+
if int(hwnd) in exclude or not user32.IsWindowVisible(hwnd):
|
|
125
|
+
return True
|
|
126
|
+
rect = wintypes.RECT()
|
|
127
|
+
if not user32.GetWindowRect(hwnd, ctypes.byref(rect)):
|
|
128
|
+
return True
|
|
129
|
+
width = rect.right - rect.left
|
|
130
|
+
height = rect.bottom - rect.top
|
|
131
|
+
if width < 80 or height < 40:
|
|
132
|
+
return True
|
|
133
|
+
class_buffer = ctypes.create_unicode_buffer(64)
|
|
134
|
+
user32.GetClassNameW(hwnd, class_buffer, 64)
|
|
135
|
+
if class_buffer.value in _PLATFORM_SKIP_CLASSES:
|
|
136
|
+
return True
|
|
137
|
+
platforms.append((rect.left, rect.right, rect.top))
|
|
138
|
+
return True
|
|
139
|
+
|
|
140
|
+
user32.EnumWindows(_collect, 0)
|
|
141
|
+
return platforms
|
|
142
|
+
except Exception as error: # pragma: no cover - Win32 boundary
|
|
143
|
+
front_engine_logger.warning(f"[windows_platforms] error: {error!r}")
|
|
144
|
+
return []
|
|
145
|
+
|
|
146
|
+
|
|
99
147
|
def message_bucket(hour: int) -> str:
|
|
100
148
|
"""依小時回傳時段 / Time-of-day bucket for the given hour."""
|
|
101
149
|
hour = int(hour) % 24
|
|
@@ -252,6 +300,12 @@ class PetMotion:
|
|
|
252
300
|
self.asleep = False
|
|
253
301
|
self.climb = bool(climb)
|
|
254
302
|
self.surface = SURFACE_FLOOR
|
|
303
|
+
# 可站立的視窗平台 (left, right, top_y);站在平台上時的狀態
|
|
304
|
+
# Standable window platforms (left, right, top_y) and platform state.
|
|
305
|
+
self.platforms: list = []
|
|
306
|
+
self.on_platform = False
|
|
307
|
+
self.platform_span: Optional[Tuple[float, float]] = None
|
|
308
|
+
self.ground_feet = 0.0
|
|
255
309
|
|
|
256
310
|
@property
|
|
257
311
|
def facing_left(self) -> bool:
|
|
@@ -260,6 +314,10 @@ class PetMotion:
|
|
|
260
314
|
def set_bounds(self, bounds: Tuple[int, int, int, int]) -> None:
|
|
261
315
|
self.bounds = bounds
|
|
262
316
|
|
|
317
|
+
def set_platforms(self, platforms) -> None:
|
|
318
|
+
"""設定可站立的視窗上緣平台 / Set standable window top-edge platforms."""
|
|
319
|
+
self.platforms = list(platforms)
|
|
320
|
+
|
|
263
321
|
def set_target(self, x: float, y: float) -> None:
|
|
264
322
|
self.target = (float(x), float(y))
|
|
265
323
|
|
|
@@ -270,6 +328,8 @@ class PetMotion:
|
|
|
270
328
|
self._airborne = True
|
|
271
329
|
self.asleep = False
|
|
272
330
|
self.surface = SURFACE_FLOOR
|
|
331
|
+
self.on_platform = False
|
|
332
|
+
self.platform_span = None
|
|
273
333
|
|
|
274
334
|
def step(self) -> Tuple[int, int]:
|
|
275
335
|
left, top, right, bottom = self.bounds
|
|
@@ -280,38 +340,19 @@ class PetMotion:
|
|
|
280
340
|
return self._step_wander(left, top, right, bottom)
|
|
281
341
|
return self._step_floor(left, top, right, bottom, floor_y)
|
|
282
342
|
|
|
283
|
-
# --- floor / gravity / climbing ---
|
|
343
|
+
# --- floor / gravity / climbing / window platforms ---
|
|
284
344
|
def _step_floor(self, left, top, right, bottom, floor_y) -> Tuple[int, int]:
|
|
285
|
-
airborne = self._airborne or (
|
|
345
|
+
airborne = self._airborne or (
|
|
346
|
+
not self.on_platform and self.surface == SURFACE_FLOOR and self.y < floor_y - 0.5
|
|
347
|
+
)
|
|
286
348
|
if airborne:
|
|
287
|
-
self.
|
|
288
|
-
|
|
289
|
-
self.
|
|
290
|
-
if self.x <= left:
|
|
291
|
-
self.x = float(left)
|
|
292
|
-
self.vx = abs(self.vx) * self.WALL_DAMPING
|
|
293
|
-
elif self.x + self.width >= right:
|
|
294
|
-
self.x = float(right - self.width)
|
|
295
|
-
self.vx = -abs(self.vx) * self.WALL_DAMPING
|
|
296
|
-
if self.y <= top:
|
|
297
|
-
self.y = float(top)
|
|
298
|
-
self.vy = abs(self.vy) * self.WALL_DAMPING
|
|
299
|
-
if self.y >= floor_y:
|
|
300
|
-
self.y = float(floor_y)
|
|
301
|
-
if abs(self.vy) > self.BOUNCE_THRESHOLD:
|
|
302
|
-
self.vy = -self.vy * self.BOUNCE_DAMPING
|
|
303
|
-
else:
|
|
304
|
-
self.vy = 0.0
|
|
305
|
-
self._airborne = False
|
|
306
|
-
self.surface = SURFACE_FLOOR
|
|
307
|
-
self.vx = float(self.speed) if self.vx >= 0 else float(-self.speed)
|
|
308
|
-
self._new_state(force_walk=True)
|
|
309
|
-
return int(self.x), int(self.y)
|
|
310
|
-
|
|
349
|
+
return self._step_fall(left, top, right, bottom, floor_y)
|
|
350
|
+
if self.on_platform:
|
|
351
|
+
return self._step_platform(left, top, right, bottom, floor_y)
|
|
311
352
|
if self.surface != SURFACE_FLOOR:
|
|
312
353
|
return self._step_climb(left, top, right, bottom, floor_y)
|
|
313
354
|
|
|
314
|
-
# grounded on the floor: random walk / idle, with a chance to climb a wall
|
|
355
|
+
# grounded on the screen floor: random walk / idle, with a chance to climb a wall
|
|
315
356
|
self.y = float(floor_y)
|
|
316
357
|
if self._state_ticks <= 0:
|
|
317
358
|
self._new_state()
|
|
@@ -335,6 +376,84 @@ class PetMotion:
|
|
|
335
376
|
self.vx = -abs(self.vx)
|
|
336
377
|
return int(self.x), int(self.y)
|
|
337
378
|
|
|
379
|
+
def _step_fall(self, left, top, right, bottom, floor_y) -> Tuple[int, int]:
|
|
380
|
+
"""落下:撞牆/天花板反彈,並在越過視窗平台或螢幕地板時落地。"""
|
|
381
|
+
prev_feet = self.y + self.height
|
|
382
|
+
self.vy += self.GRAVITY
|
|
383
|
+
self.x += self.vx
|
|
384
|
+
self.y += self.vy
|
|
385
|
+
if self.x <= left:
|
|
386
|
+
self.x = float(left)
|
|
387
|
+
self.vx = abs(self.vx) * self.WALL_DAMPING
|
|
388
|
+
elif self.x + self.width >= right:
|
|
389
|
+
self.x = float(right - self.width)
|
|
390
|
+
self.vx = -abs(self.vx) * self.WALL_DAMPING
|
|
391
|
+
if self.y <= top:
|
|
392
|
+
self.y = float(top)
|
|
393
|
+
self.vy = abs(self.vy) * self.WALL_DAMPING
|
|
394
|
+
new_feet = self.y + self.height
|
|
395
|
+
center_x = self.x + self.width / 2.0
|
|
396
|
+
|
|
397
|
+
land_feet = None
|
|
398
|
+
land_span = None
|
|
399
|
+
for platform_left, platform_right, platform_y in self.platforms:
|
|
400
|
+
if platform_left <= center_x <= platform_right and prev_feet <= platform_y <= new_feet:
|
|
401
|
+
if land_feet is None or platform_y < land_feet:
|
|
402
|
+
land_feet = float(platform_y)
|
|
403
|
+
land_span = (float(platform_left), float(platform_right))
|
|
404
|
+
if prev_feet <= bottom <= new_feet and (land_feet is None or bottom < land_feet):
|
|
405
|
+
land_feet = float(bottom)
|
|
406
|
+
land_span = None
|
|
407
|
+
|
|
408
|
+
if land_feet is not None:
|
|
409
|
+
self.y = float(land_feet - self.height)
|
|
410
|
+
if abs(self.vy) > self.BOUNCE_THRESHOLD:
|
|
411
|
+
self.vy = -self.vy * self.BOUNCE_DAMPING
|
|
412
|
+
else:
|
|
413
|
+
self.vy = 0.0
|
|
414
|
+
self._airborne = False
|
|
415
|
+
self.surface = SURFACE_FLOOR
|
|
416
|
+
self.on_platform = land_span is not None
|
|
417
|
+
self.platform_span = land_span
|
|
418
|
+
self.ground_feet = land_feet
|
|
419
|
+
self.vx = float(self.speed) if self.vx >= 0 else float(-self.speed)
|
|
420
|
+
self._new_state(force_walk=True)
|
|
421
|
+
return int(self.x), int(self.y)
|
|
422
|
+
|
|
423
|
+
def _platform_under(self) -> Optional[Tuple[float, float]]:
|
|
424
|
+
"""回傳目前站立平台的水平範圍;平台已消失(視窗移走/關閉)則回傳 None。"""
|
|
425
|
+
body_left = self.x
|
|
426
|
+
body_right = self.x + self.width
|
|
427
|
+
for platform_left, platform_right, platform_y in self.platforms:
|
|
428
|
+
if abs(platform_y - self.ground_feet) <= 2.0 and not (platform_right < body_left or platform_left > body_right):
|
|
429
|
+
return (float(platform_left), float(platform_right))
|
|
430
|
+
return None
|
|
431
|
+
|
|
432
|
+
def _step_platform(self, left, top, right, bottom, floor_y) -> Tuple[int, int]:
|
|
433
|
+
"""站在視窗平台上走動;到平台兩端轉向;平台消失則掉落。"""
|
|
434
|
+
span = self._platform_under()
|
|
435
|
+
if span is None:
|
|
436
|
+
self._airborne = True
|
|
437
|
+
self.on_platform = False
|
|
438
|
+
self.platform_span = None
|
|
439
|
+
return self._step_fall(left, top, right, bottom, floor_y)
|
|
440
|
+
self.platform_span = span
|
|
441
|
+
span_left, span_right = span
|
|
442
|
+
self.y = float(self.ground_feet - self.height)
|
|
443
|
+
if self._state_ticks <= 0:
|
|
444
|
+
self._new_state()
|
|
445
|
+
self._state_ticks -= 1
|
|
446
|
+
if self.state != "walk":
|
|
447
|
+
return int(self.x), int(self.y)
|
|
448
|
+
self.x += self.vx
|
|
449
|
+
if self.x <= span_left:
|
|
450
|
+
self.x = float(span_left)
|
|
451
|
+
self.vx = abs(self.vx)
|
|
452
|
+
elif self.x + self.width >= span_right:
|
|
453
|
+
self.x = float(span_right - self.width)
|
|
454
|
+
self.vx = -abs(self.vx)
|
|
455
|
+
return int(self.x), int(self.y)
|
|
456
|
+
|
|
338
457
|
def _step_climb(self, left, top, right, bottom, floor_y) -> Tuple[int, int]:
|
|
339
458
|
"""沿螢幕邊緣爬行;隨機放手則掉落 / Crawl the screen perimeter; may let go and fall."""
|
|
340
459
|
if self._rng.random() < self.DROP_CHANCE:
|
|
@@ -453,10 +572,11 @@ class DesktopPetWidget(BaseWidget):
|
|
|
453
572
|
|
|
454
573
|
def __init__(self, image_path: str, size: int = 128, speed: int = 3,
|
|
455
574
|
behaviour: str = BEHAVIOUR_FLOOR, climb: bool = True, talk: bool = True,
|
|
456
|
-
sound_path: Optional[str] = None):
|
|
575
|
+
sound_path: Optional[str] = None, sit_on_windows: bool = True):
|
|
457
576
|
front_engine_logger.info(
|
|
458
577
|
f"[DesktopPetWidget] Init | path={image_path}, size={size}, speed={speed}, "
|
|
459
|
-
f"behaviour={behaviour}, climb={climb}, talk={talk}, sound={sound_path}"
|
|
578
|
+
f"behaviour={behaviour}, climb={climb}, talk={talk}, sound={sound_path}, "
|
|
579
|
+
f"sit_on_windows={sit_on_windows}"
|
|
460
580
|
)
|
|
461
581
|
super().__init__()
|
|
462
582
|
self.opacity = 1.0
|
|
@@ -494,6 +614,8 @@ class DesktopPetWidget(BaseWidget):
|
|
|
494
614
|
self._messages = self._load_messages()
|
|
495
615
|
self._sound: Optional[QSoundEffect] = None
|
|
496
616
|
self._init_sound(sound_path)
|
|
617
|
+
self._sit_on_windows = bool(sit_on_windows)
|
|
618
|
+
self._platform_tick = 0
|
|
497
619
|
self._bubble = SpeechBubble()
|
|
498
620
|
self._chatter_timer = QTimer(self)
|
|
499
621
|
self._chatter_timer.setSingleShot(True)
|
|
@@ -645,6 +767,11 @@ class DesktopPetWidget(BaseWidget):
|
|
|
645
767
|
if self.motion.behaviour == BEHAVIOUR_CHASE:
|
|
646
768
|
cursor = QCursor.pos()
|
|
647
769
|
self.motion.set_target(cursor.x(), cursor.y())
|
|
770
|
+
elif self._sit_on_windows and self.motion.behaviour == BEHAVIOUR_FLOOR:
|
|
771
|
+
self._platform_tick += 1
|
|
772
|
+
if self._platform_tick >= 10:
|
|
773
|
+
self._platform_tick = 0
|
|
774
|
+
self.motion.set_platforms(windows_platforms(exclude_hwnds=(int(self.winId()),)))
|
|
648
775
|
x, y = self.motion.step()
|
|
649
776
|
self.move(x, y)
|
|
650
777
|
self._set_active_sprite(self._visual_state())
|
|
@@ -76,6 +76,8 @@ class PetSettingUI(QWidget):
|
|
|
76
76
|
self.climb_checkbox.setChecked(True)
|
|
77
77
|
self.talk_checkbox = QCheckBox(language_wrapper.language_word_dict.get("pet_talk_label", "Speech bubbles"))
|
|
78
78
|
self.talk_checkbox.setChecked(True)
|
|
79
|
+
self.sit_checkbox = QCheckBox(language_wrapper.language_word_dict.get("pet_sit_label", "Sit on windows"))
|
|
80
|
+
self.sit_checkbox.setChecked(True)
|
|
79
81
|
|
|
80
82
|
# Start
|
|
81
83
|
self.start_button = QPushButton(language_wrapper.language_word_dict.get("pet_start", "Spawn pet"))
|
|
@@ -102,6 +104,7 @@ class PetSettingUI(QWidget):
|
|
|
102
104
|
self.grid_layout.addWidget(self.behaviour_combobox, 3, 1)
|
|
103
105
|
self.grid_layout.addWidget(self.climb_checkbox, 3, 2)
|
|
104
106
|
self.grid_layout.addWidget(self.talk_checkbox, 2, 2)
|
|
107
|
+
self.grid_layout.addWidget(self.sit_checkbox, 4, 2)
|
|
105
108
|
self.grid_layout.addWidget(self.start_button, 4, 0)
|
|
106
109
|
self.grid_layout.addWidget(self.recent_files_label, 5, 0)
|
|
107
110
|
self.grid_layout.addWidget(self.recent_files_combobox, 5, 1)
|
|
@@ -118,6 +121,7 @@ class PetSettingUI(QWidget):
|
|
|
118
121
|
climb=self.climb_checkbox.isChecked(),
|
|
119
122
|
talk=self.talk_checkbox.isChecked(),
|
|
120
123
|
sound_path=self.pet_sound_path,
|
|
124
|
+
sit_on_windows=self.sit_checkbox.isChecked(),
|
|
121
125
|
)
|
|
122
126
|
pet.clone_requested.connect(self._spawn_pet)
|
|
123
127
|
pet.set_pet_window_flag()
|
|
@@ -203,6 +207,7 @@ class PetSettingUI(QWidget):
|
|
|
203
207
|
"climb": self.climb_checkbox.isChecked(),
|
|
204
208
|
"talk": self.talk_checkbox.isChecked(),
|
|
205
209
|
"sound": self.pet_sound_path,
|
|
210
|
+
"sit": self.sit_checkbox.isChecked(),
|
|
206
211
|
}
|
|
207
212
|
|
|
208
213
|
def set_state(self, state: dict) -> None:
|
|
@@ -228,3 +233,5 @@ class PetSettingUI(QWidget):
|
|
|
228
233
|
self.talk_checkbox.setChecked(bool(state["talk"]))
|
|
229
234
|
if state.get("sound"):
|
|
230
235
|
self.pet_sound_path = str(state["sound"])
|
|
236
|
+
if "sit" in state:
|
|
237
|
+
self.sit_checkbox.setChecked(bool(state["sit"]))
|
|
@@ -229,6 +229,7 @@ english_word_dict = {
|
|
|
229
229
|
"pet_choose_sound": "Choose sound (optional)",
|
|
230
230
|
"pet_pack_empty": "No sprites (walk/idle/sleep/climb/fall/drag) found in that folder.",
|
|
231
231
|
"pet_talk_label": "Speech bubbles",
|
|
232
|
+
"pet_sit_label": "Sit on windows",
|
|
232
233
|
"pet_chatter_morning": "Good morning!|Rise and shine!|Ready for the day?",
|
|
233
234
|
"pet_chatter_afternoon": "Good afternoon!|Taking a break?|Keep it up!",
|
|
234
235
|
"pet_chatter_evening": "Good evening!|How was your day?|Almost done?",
|
{frontengine-1.0.9 → frontengine-1.0.10}/frontengine/utils/multi_language/traditional_chinese.py
RENAMED
|
@@ -230,6 +230,7 @@ traditional_chinese_word_dict = {
|
|
|
230
230
|
"pet_choose_sound": "選擇音效(選填)",
|
|
231
231
|
"pet_pack_empty": "該資料夾找不到精靈檔(walk/idle/sleep/climb/fall/drag)。",
|
|
232
232
|
"pet_talk_label": "對話泡泡",
|
|
233
|
+
"pet_sit_label": "站在視窗上",
|
|
233
234
|
"pet_chatter_morning": "早安!|新的一天開始囉!|準備好了嗎?",
|
|
234
235
|
"pet_chatter_afternoon": "午安!|要不要休息一下?|繼續加油!",
|
|
235
236
|
"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.10
|
|
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.9 → frontengine-1.0.10}/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.9 → frontengine-1.0.10}/frontengine/ui/page/particle/particle_setting_ui.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/gif.py
RENAMED
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/image.py
RENAMED
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/registry.py
RENAMED
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/sound.py
RENAMED
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/text.py
RENAMED
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/video.py
RENAMED
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_page/web.py
RENAMED
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/frontengine/ui/page/scene_setting/scene_setting_ui.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/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.9 → frontengine-1.0.10}/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.9 → frontengine-1.0.10}/frontengine/utils/multi_language/language_wrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/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.9 → frontengine-1.0.10}/frontengine/utils/smart_pause/smart_pause_service.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.9 → frontengine-1.0.10}/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
|