frontengine 1.0.5__tar.gz → 1.0.6__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.5 → frontengine-1.0.6}/PKG-INFO +1 -1
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/pet/desktop_pet.py +128 -7
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/pet/pet_setting_ui.py +7 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/multi_language/english.py +6 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/multi_language/traditional_chinese.py +6 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine.egg-info/PKG-INFO +1 -1
- {frontengine-1.0.5 → frontengine-1.0.6}/pyproject.toml +1 -1
- {frontengine-1.0.5 → frontengine-1.0.6}/LICENSE +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/README.md +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/__main__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/base_widget.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/gif/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/gif/paint_gif.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/image/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/image/paint_image.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/load/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/load/load_someone_make_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/overlay_factory.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/particle/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/particle/particle_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/pet/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/scene/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/scene/extend_graphic_scene.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/scene/extend_graphic_view.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/scene/scene.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/sound_player/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/sound_player/sound_effect.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/sound_player/sound_player.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/text/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/text/draw_text.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/video/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/video/video_player.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/web/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/web/webview.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/show/window_helpers.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/system_tray/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/system_tray/extend_system_tray.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/color/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/color/global_color.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/dialog/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/dialog/choose_file_dialog.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/dialog/hotkey_settings_dialog.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/dialog/save_file_dialog.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/main_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/menu/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/menu/help_menu.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/menu/how_to_menu.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/menu/language_menu.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/menu/preset_menu.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/menu/settings_menu.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/control_center/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/control_center/control_center_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/gif/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/gif/gif_setting_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/image/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/image/image_setting_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/particle/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/particle/particle_setting_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/pet/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_manager.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/gif.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/image.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/registry.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/sound.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/text.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/video.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/web.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_setting_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/sound_player/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/sound_player/sound_player_setting_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/text/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/text/text_setting_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/utils.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/video/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/video/video_setting_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/web/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/web/web_setting_ui.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/user_setting/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/user_setting/preset_repository.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/user_setting/scene_setting.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/user_setting/user_setting_file.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/browser/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/browser/browser.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/critical_exit/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/critical_exit/check_key_is_press.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/critical_exit/critical_exit.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/critical_exit/win32_vk.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/exception/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/exception/exception_tags.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/exception/exceptions.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/file/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/file/open/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/file/open/open_file.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/file/save/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/file/save/save_file.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/hotkey/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/hotkey/hotkey_service.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/json/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/json/json_file.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/json/json_repository.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/json_format/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/json_format/json_process.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/logging/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/logging/loggin_instance.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/multi_language/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/multi_language/france.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/multi_language/germany.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/multi_language/italy.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/multi_language/language_wrapper.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/multi_language/russian.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/multi_language/simplified_chinese.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/preset_schedule/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/preset_schedule/preset_schedule_service.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/redirect_manager/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/redirect_manager/redirect_manager_class.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/smart_pause/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/smart_pause/smart_pause_service.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/theme_schedule/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/theme_schedule/theme_schedule_service.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/web_url.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/worker/__init__.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine/worker/qthread_worker.py +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine.egg-info/SOURCES.txt +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine.egg-info/dependency_links.txt +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine.egg-info/entry_points.txt +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine.egg-info/requires.txt +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/frontengine.egg-info/top_level.txt +0 -0
- {frontengine-1.0.5 → frontengine-1.0.6}/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.6
|
|
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,10 +1,11 @@
|
|
|
1
1
|
import random as _random_module
|
|
2
|
+
from datetime import datetime
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
from typing import Optional, Tuple
|
|
4
5
|
|
|
5
6
|
from PySide6.QtCore import Qt, QRect, QTimer, Signal
|
|
6
|
-
from PySide6.QtGui import QAction, QCursor, QMovie, QPainter, QPixmap, QTransform
|
|
7
|
-
from PySide6.QtWidgets import QMenu, QMessageBox
|
|
7
|
+
from PySide6.QtGui import QAction, QColor, QCursor, QFont, QFontMetrics, QMovie, QPainter, QPixmap, QTransform
|
|
8
|
+
from PySide6.QtWidgets import QMenu, QMessageBox, QWidget
|
|
8
9
|
|
|
9
10
|
from frontengine.show.base_widget import BaseWidget
|
|
10
11
|
from frontengine.show.window_helpers import apply_overlay_window_flags
|
|
@@ -80,6 +81,74 @@ def derive_visual_state(dragging: bool, airborne: bool, surface: str, motion_sta
|
|
|
80
81
|
return STATE_WALK
|
|
81
82
|
|
|
82
83
|
|
|
84
|
+
def message_bucket(hour: int) -> str:
|
|
85
|
+
"""依小時回傳時段 / Time-of-day bucket for the given hour."""
|
|
86
|
+
hour = int(hour) % 24
|
|
87
|
+
if 5 <= hour < 12:
|
|
88
|
+
return "morning"
|
|
89
|
+
if 12 <= hour < 18:
|
|
90
|
+
return "afternoon"
|
|
91
|
+
if 18 <= hour < 22:
|
|
92
|
+
return "evening"
|
|
93
|
+
return "night"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def pick_message(hour: int, rng, messages: dict) -> str:
|
|
97
|
+
"""
|
|
98
|
+
依時段從對應句庫(加上通用句庫)隨機挑一句台詞;句庫皆空回傳空字串。
|
|
99
|
+
Pick a chatter line from the time bucket plus the generic pool. rng needs
|
|
100
|
+
a ``randrange`` method (injectable for tests).
|
|
101
|
+
"""
|
|
102
|
+
pool = list(messages.get(message_bucket(hour), [])) + list(messages.get("any", []))
|
|
103
|
+
if not pool:
|
|
104
|
+
return ""
|
|
105
|
+
return pool[rng.randrange(len(pool))]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class SpeechBubble(QWidget):
|
|
109
|
+
"""寵物頭上的小對話泡泡,數秒後自動消失 / A small speech bubble that auto-hides."""
|
|
110
|
+
|
|
111
|
+
def __init__(self) -> None:
|
|
112
|
+
super().__init__()
|
|
113
|
+
self._text = ""
|
|
114
|
+
self._font = QFont()
|
|
115
|
+
self._font.setPointSize(11)
|
|
116
|
+
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
|
117
|
+
apply_overlay_window_flags(self, show_on_bottom=False, allow_input=False)
|
|
118
|
+
self._hide_timer = QTimer(self)
|
|
119
|
+
self._hide_timer.setSingleShot(True)
|
|
120
|
+
self._hide_timer.timeout.connect(self.hide)
|
|
121
|
+
|
|
122
|
+
def show_message(self, text: str, anchor: QWidget, duration_ms: int = 4000) -> None:
|
|
123
|
+
self._text = text
|
|
124
|
+
width = min(260, QFontMetrics(self._font).horizontalAdvance(text) + 28)
|
|
125
|
+
self.resize(max(60, width), 44)
|
|
126
|
+
self.reposition(anchor)
|
|
127
|
+
self.show()
|
|
128
|
+
self.raise_()
|
|
129
|
+
self.update()
|
|
130
|
+
self._hide_timer.start(max(500, int(duration_ms)))
|
|
131
|
+
|
|
132
|
+
def reposition(self, anchor: QWidget) -> None:
|
|
133
|
+
geo = anchor.frameGeometry()
|
|
134
|
+
self.move(geo.center().x() - self.width() // 2, geo.top() - self.height() - 6)
|
|
135
|
+
|
|
136
|
+
def paintEvent(self, event) -> None:
|
|
137
|
+
painter = QPainter(self)
|
|
138
|
+
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
|
|
139
|
+
rect = self.rect().adjusted(1, 1, -1, -1)
|
|
140
|
+
painter.setBrush(QColor(255, 255, 240, 235))
|
|
141
|
+
painter.setPen(QColor(90, 90, 90))
|
|
142
|
+
painter.drawRoundedRect(rect, 8, 8)
|
|
143
|
+
painter.setPen(QColor(30, 30, 30))
|
|
144
|
+
painter.setFont(self._font)
|
|
145
|
+
painter.drawText(
|
|
146
|
+
rect.adjusted(8, 2, -8, -2),
|
|
147
|
+
int(Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextWordWrap),
|
|
148
|
+
self._text,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
83
152
|
class PetMotion:
|
|
84
153
|
"""
|
|
85
154
|
純邏輯的寵物移動模型(不依賴 Qt,完全可測試)。包含:
|
|
@@ -317,10 +386,10 @@ class DesktopPetWidget(BaseWidget):
|
|
|
317
386
|
clone_requested = Signal()
|
|
318
387
|
|
|
319
388
|
def __init__(self, image_path: str, size: int = 128, speed: int = 3,
|
|
320
|
-
behaviour: str = BEHAVIOUR_FLOOR, climb: bool = True):
|
|
389
|
+
behaviour: str = BEHAVIOUR_FLOOR, climb: bool = True, talk: bool = True):
|
|
321
390
|
front_engine_logger.info(
|
|
322
391
|
f"[DesktopPetWidget] Init | path={image_path}, size={size}, speed={speed}, "
|
|
323
|
-
f"behaviour={behaviour}, climb={climb}"
|
|
392
|
+
f"behaviour={behaviour}, climb={climb}, talk={talk}"
|
|
324
393
|
)
|
|
325
394
|
super().__init__()
|
|
326
395
|
self.opacity = 1.0
|
|
@@ -350,6 +419,16 @@ class DesktopPetWidget(BaseWidget):
|
|
|
350
419
|
self._timer = QTimer(self)
|
|
351
420
|
self._timer.timeout.connect(self._on_tick)
|
|
352
421
|
|
|
422
|
+
# Speech bubbles / chatter
|
|
423
|
+
self._talk = bool(talk)
|
|
424
|
+
self._moved = False
|
|
425
|
+
self._chatter_rng = _random_module.SystemRandom()
|
|
426
|
+
self._messages = self._load_messages()
|
|
427
|
+
self._bubble = SpeechBubble()
|
|
428
|
+
self._chatter_timer = QTimer(self)
|
|
429
|
+
self._chatter_timer.setSingleShot(True)
|
|
430
|
+
self._chatter_timer.timeout.connect(self._on_chatter)
|
|
431
|
+
|
|
353
432
|
self.menu = QMenu(self)
|
|
354
433
|
self.clone_action = QAction(language_wrapper.language_word_dict.get("pet_clone", "Clone"), self)
|
|
355
434
|
self.clone_action.triggered.connect(self.clone_requested.emit)
|
|
@@ -426,6 +505,38 @@ class DesktopPetWidget(BaseWidget):
|
|
|
426
505
|
self.motion.y = float(bottom - self.pet_size)
|
|
427
506
|
self.move(int(self.motion.x), int(self.motion.y))
|
|
428
507
|
self._timer.start(max(10, int(interval_ms)))
|
|
508
|
+
self._schedule_chatter()
|
|
509
|
+
|
|
510
|
+
def _load_messages(self) -> dict:
|
|
511
|
+
d = language_wrapper.language_word_dict
|
|
512
|
+
|
|
513
|
+
def lines(key: str, fallback: str) -> list:
|
|
514
|
+
return [part.strip() for part in str(d.get(key, fallback)).split("|") if part.strip()]
|
|
515
|
+
|
|
516
|
+
return {
|
|
517
|
+
"morning": lines("pet_chatter_morning", "Good morning!|Ready for the day?"),
|
|
518
|
+
"afternoon": lines("pet_chatter_afternoon", "Good afternoon!|Taking a break?"),
|
|
519
|
+
"evening": lines("pet_chatter_evening", "Good evening!|How was your day?"),
|
|
520
|
+
"night": lines("pet_chatter_night", "It's late - get some rest!|Still up?"),
|
|
521
|
+
"any": lines("pet_chatter_any", "Hi there!|(^_^)|Keep going!"),
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
def _schedule_chatter(self) -> None:
|
|
525
|
+
if self._talk:
|
|
526
|
+
self._chatter_timer.start(self._chatter_rng.randint(15000, 35000))
|
|
527
|
+
|
|
528
|
+
def _on_chatter(self) -> None:
|
|
529
|
+
self.say()
|
|
530
|
+
self._schedule_chatter()
|
|
531
|
+
|
|
532
|
+
def say(self, text: Optional[str] = None) -> None:
|
|
533
|
+
"""顯示一句台詞(text 為 None 時依時段隨機挑)。"""
|
|
534
|
+
if not self._talk:
|
|
535
|
+
return
|
|
536
|
+
if text is None:
|
|
537
|
+
text = pick_message(datetime.now().hour, self._chatter_rng, self._messages)
|
|
538
|
+
if text:
|
|
539
|
+
self._bubble.show_message(text, self)
|
|
429
540
|
|
|
430
541
|
def _on_tick(self) -> None:
|
|
431
542
|
if self._dragging:
|
|
@@ -437,11 +548,14 @@ class DesktopPetWidget(BaseWidget):
|
|
|
437
548
|
x, y = self.motion.step()
|
|
438
549
|
self.move(x, y)
|
|
439
550
|
self._set_active_sprite(self._visual_state())
|
|
551
|
+
if self._bubble.isVisible():
|
|
552
|
+
self._bubble.reposition(self)
|
|
440
553
|
|
|
441
554
|
# --- dragging + throwing ---
|
|
442
555
|
def mousePressEvent(self, event) -> None:
|
|
443
556
|
if event.button() == Qt.MouseButton.LeftButton:
|
|
444
557
|
self._dragging = True
|
|
558
|
+
self._moved = False
|
|
445
559
|
self._last_move_delta = (0, 0)
|
|
446
560
|
self._drag_offset = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
|
|
447
561
|
self._set_active_sprite(STATE_DRAG)
|
|
@@ -451,6 +565,7 @@ class DesktopPetWidget(BaseWidget):
|
|
|
451
565
|
if self._dragging and self._drag_offset is not None:
|
|
452
566
|
new_top_left = event.globalPosition().toPoint() - self._drag_offset
|
|
453
567
|
self._last_move_delta = (new_top_left.x() - self.x(), new_top_left.y() - self.y())
|
|
568
|
+
self._moved = True
|
|
454
569
|
self.move(new_top_left)
|
|
455
570
|
super().mouseMoveEvent(event)
|
|
456
571
|
|
|
@@ -459,9 +574,12 @@ class DesktopPetWidget(BaseWidget):
|
|
|
459
574
|
self._dragging = False
|
|
460
575
|
self.motion.x = float(self.x())
|
|
461
576
|
self.motion.y = float(self.y())
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
self.motion.
|
|
577
|
+
if self._moved:
|
|
578
|
+
# Fling with the momentum of the last drag movement (floor mode).
|
|
579
|
+
if self.motion.behaviour == BEHAVIOUR_FLOOR:
|
|
580
|
+
self.motion.throw(self._last_move_delta[0], self._last_move_delta[1])
|
|
581
|
+
else:
|
|
582
|
+
self.say() # a click (no drag) makes the pet talk
|
|
465
583
|
super().mouseReleaseEvent(event)
|
|
466
584
|
|
|
467
585
|
def contextMenuEvent(self, event) -> None:
|
|
@@ -470,6 +588,9 @@ class DesktopPetWidget(BaseWidget):
|
|
|
470
588
|
def closeEvent(self, event) -> None:
|
|
471
589
|
if self._timer.isActive():
|
|
472
590
|
self._timer.stop()
|
|
591
|
+
if self._chatter_timer.isActive():
|
|
592
|
+
self._chatter_timer.stop()
|
|
593
|
+
self._bubble.close()
|
|
473
594
|
for kind, obj in self._sprites.values():
|
|
474
595
|
if kind == "movie":
|
|
475
596
|
obj.stop()
|
|
@@ -69,6 +69,8 @@ class PetSettingUI(QWidget):
|
|
|
69
69
|
# Climb walls / ceiling (only meaningful in floor mode)
|
|
70
70
|
self.climb_checkbox = QCheckBox(language_wrapper.language_word_dict.get("pet_climb_label", "Climb walls"))
|
|
71
71
|
self.climb_checkbox.setChecked(True)
|
|
72
|
+
self.talk_checkbox = QCheckBox(language_wrapper.language_word_dict.get("pet_talk_label", "Speech bubbles"))
|
|
73
|
+
self.talk_checkbox.setChecked(True)
|
|
72
74
|
|
|
73
75
|
# Start
|
|
74
76
|
self.start_button = QPushButton(language_wrapper.language_word_dict.get("pet_start", "Spawn pet"))
|
|
@@ -93,6 +95,7 @@ class PetSettingUI(QWidget):
|
|
|
93
95
|
self.grid_layout.addWidget(self.behaviour_label, 3, 0)
|
|
94
96
|
self.grid_layout.addWidget(self.behaviour_combobox, 3, 1)
|
|
95
97
|
self.grid_layout.addWidget(self.climb_checkbox, 3, 2)
|
|
98
|
+
self.grid_layout.addWidget(self.talk_checkbox, 2, 2)
|
|
96
99
|
self.grid_layout.addWidget(self.start_button, 4, 0)
|
|
97
100
|
self.grid_layout.addWidget(self.recent_files_label, 5, 0)
|
|
98
101
|
self.grid_layout.addWidget(self.recent_files_combobox, 5, 1)
|
|
@@ -107,6 +110,7 @@ class PetSettingUI(QWidget):
|
|
|
107
110
|
speed=int(self.speed_combobox.currentText()),
|
|
108
111
|
behaviour=self.behaviour_combobox.currentData(),
|
|
109
112
|
climb=self.climb_checkbox.isChecked(),
|
|
113
|
+
talk=self.talk_checkbox.isChecked(),
|
|
110
114
|
)
|
|
111
115
|
pet.clone_requested.connect(self._spawn_pet)
|
|
112
116
|
pet.set_pet_window_flag()
|
|
@@ -183,6 +187,7 @@ class PetSettingUI(QWidget):
|
|
|
183
187
|
"speed": self.speed_combobox.currentText(),
|
|
184
188
|
"behaviour": self.behaviour_combobox.currentData(),
|
|
185
189
|
"climb": self.climb_checkbox.isChecked(),
|
|
190
|
+
"talk": self.talk_checkbox.isChecked(),
|
|
186
191
|
}
|
|
187
192
|
|
|
188
193
|
def set_state(self, state: dict) -> None:
|
|
@@ -204,3 +209,5 @@ class PetSettingUI(QWidget):
|
|
|
204
209
|
self.behaviour_combobox.setCurrentIndex(index)
|
|
205
210
|
if "climb" in state:
|
|
206
211
|
self.climb_checkbox.setChecked(bool(state["climb"]))
|
|
212
|
+
if "talk" in state:
|
|
213
|
+
self.talk_checkbox.setChecked(bool(state["talk"]))
|
|
@@ -227,6 +227,12 @@ english_word_dict = {
|
|
|
227
227
|
"pet_clone": "Clone",
|
|
228
228
|
"pet_choose_pack": "Choose pet pack...",
|
|
229
229
|
"pet_pack_empty": "No sprites (walk/idle/climb/fall/drag) found in that folder.",
|
|
230
|
+
"pet_talk_label": "Speech bubbles",
|
|
231
|
+
"pet_chatter_morning": "Good morning!|Rise and shine!|Ready for the day?",
|
|
232
|
+
"pet_chatter_afternoon": "Good afternoon!|Taking a break?|Keep it up!",
|
|
233
|
+
"pet_chatter_evening": "Good evening!|How was your day?|Almost done?",
|
|
234
|
+
"pet_chatter_night": "It's late - get some rest!|Still up?|Sweet dreams soon~",
|
|
235
|
+
"pet_chatter_any": "Hi there!|(^_^)|Keep going!|You've got this!",
|
|
230
236
|
"pet_start": "Spawn pet",
|
|
231
237
|
"pet_message_box_text": "Pet image not found",
|
|
232
238
|
}
|
{frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/multi_language/traditional_chinese.py
RENAMED
|
@@ -228,6 +228,12 @@ traditional_chinese_word_dict = {
|
|
|
228
228
|
"pet_clone": "複製",
|
|
229
229
|
"pet_choose_pack": "選擇動作包資料夾...",
|
|
230
230
|
"pet_pack_empty": "該資料夾找不到精靈檔(walk/idle/climb/fall/drag)。",
|
|
231
|
+
"pet_talk_label": "對話泡泡",
|
|
232
|
+
"pet_chatter_morning": "早安!|新的一天開始囉!|準備好了嗎?",
|
|
233
|
+
"pet_chatter_afternoon": "午安!|要不要休息一下?|繼續加油!",
|
|
234
|
+
"pet_chatter_evening": "晚上好!|今天過得如何?|快完成了嗎?",
|
|
235
|
+
"pet_chatter_night": "很晚了,早點休息!|還沒睡嗎?|祝好夢~",
|
|
236
|
+
"pet_chatter_any": "嗨!|(^_^)|加油!|你可以的!",
|
|
231
237
|
"pet_start": "召喚寵物",
|
|
232
238
|
"pet_message_box_text": "找不到寵物圖片",
|
|
233
239
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frontengine
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.6
|
|
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.5 → frontengine-1.0.6}/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.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/image.py
RENAMED
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/registry.py
RENAMED
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/sound.py
RENAMED
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/text.py
RENAMED
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_page/video.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/frontengine/ui/page/scene_setting/scene_setting_ui.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/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.5 → frontengine-1.0.6}/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.5 → frontengine-1.0.6}/frontengine/utils/multi_language/language_wrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/multi_language/simplified_chinese.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/preset_schedule/preset_schedule_service.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/redirect_manager/redirect_manager_class.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/frontengine/utils/smart_pause/smart_pause_service.py
RENAMED
|
File without changes
|
|
File without changes
|
{frontengine-1.0.5 → frontengine-1.0.6}/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
|