frontengine 1.0.83__tar.gz → 1.0.85__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.
Files changed (473) hide show
  1. {frontengine-1.0.83/frontengine.egg-info → frontengine-1.0.85}/PKG-INFO +8 -1
  2. {frontengine-1.0.83 → frontengine-1.0.85}/README.md +7 -0
  3. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/desktop_pet.py +72 -14
  4. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/pet_profile_session.py +2 -2
  5. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/puppet_pet.py +19 -4
  6. frontengine-1.0.85/frontengine/show/pet/puppet_stroll.py +132 -0
  7. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/wardrobe.py +6 -3
  8. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/pet_asset_install.py +30 -0
  9. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/pet_customization.py +1 -1
  10. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/pet/pet_setting_ui.py +55 -7
  11. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/user_setting/pet_profile_schema.py +2 -2
  12. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/multi_language/english.py +3 -1
  13. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/multi_language/france.py +3 -1
  14. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/multi_language/germany.py +3 -1
  15. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/multi_language/italy.py +3 -1
  16. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/multi_language/russian.py +3 -1
  17. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/multi_language/simplified_chinese.py +3 -1
  18. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/multi_language/traditional_chinese.py +3 -1
  19. {frontengine-1.0.83 → frontengine-1.0.85/frontengine.egg-info}/PKG-INFO +8 -1
  20. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine.egg-info/SOURCES.txt +1 -0
  21. {frontengine-1.0.83 → frontengine-1.0.85}/pyproject.toml +1 -1
  22. {frontengine-1.0.83 → frontengine-1.0.85}/LICENSE +0 -0
  23. {frontengine-1.0.83 → frontengine-1.0.85}/MANIFEST.in +0 -0
  24. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/__init__.py +0 -0
  25. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/__main__.py +0 -0
  26. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/__init__.py +0 -0
  27. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/base_widget.py +0 -0
  28. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/camera/__init__.py +0 -0
  29. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/camera/camera_widget.py +0 -0
  30. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/canvas/__init__.py +0 -0
  31. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/canvas/whiteboard_controls.py +0 -0
  32. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/canvas/whiteboard_widget.py +0 -0
  33. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/capture/__init__.py +0 -0
  34. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/capture/region_capture.py +0 -0
  35. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/compositor/__init__.py +0 -0
  36. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/compositor/gl_widget.py +0 -0
  37. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/compositor/layers.py +0 -0
  38. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/compositor/widget.py +0 -0
  39. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/draggable_window.py +0 -0
  40. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/focus_shield/__init__.py +0 -0
  41. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/focus_shield/focus_shield_widget.py +0 -0
  42. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/freeze/__init__.py +0 -0
  43. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/freeze/freeze_widget.py +0 -0
  44. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/gif/__init__.py +0 -0
  45. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/gif/paint_gif.py +0 -0
  46. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/image/__init__.py +0 -0
  47. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/image/paint_image.py +0 -0
  48. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/load/__init__.py +0 -0
  49. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/load/load_someone_make_ui.py +0 -0
  50. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/measure/__init__.py +0 -0
  51. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/measure/measure_widget.py +0 -0
  52. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/monitor/__init__.py +0 -0
  53. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/monitor/monitor_widget.py +0 -0
  54. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/notes/__init__.py +0 -0
  55. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/notes/sticky_note_widget.py +0 -0
  56. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/notes/todo_widget.py +0 -0
  57. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/overlay_factory.py +0 -0
  58. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/particle/__init__.py +0 -0
  59. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/particle/particle_ui.py +0 -0
  60. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/__init__.py +0 -0
  61. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/asset_library.py +0 -0
  62. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/ball_toy.py +0 -0
  63. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/call_target.py +0 -0
  64. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/companion_menu.py +0 -0
  65. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/focus_companions.py +0 -0
  66. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/focus_placement.py +0 -0
  67. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/__init__.py +0 -0
  68. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/assemble.py +0 -0
  69. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/builder.py +0 -0
  70. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/cast.py +0 -0
  71. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/cast_bolt.py +0 -0
  72. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/cast_gill.py +0 -0
  73. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/cast_ink.py +0 -0
  74. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/cast_mochi.py +0 -0
  75. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/cast_moss.py +0 -0
  76. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/cast_pip.py +0 -0
  77. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/faces.py +0 -0
  78. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/garments.py +0 -0
  79. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/ink.py +0 -0
  80. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/labels.py +0 -0
  81. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/library.py +0 -0
  82. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/puppet_export.py +0 -0
  83. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/rig.py +0 -0
  84. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprite_sheet.py +0 -0
  85. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-bolt-climb.png +0 -0
  86. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-bolt-walk.png +0 -0
  87. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-gill-climb.png +0 -0
  88. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-gill-walk.png +0 -0
  89. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-ink-climb.png +0 -0
  90. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-ink-walk.png +0 -0
  91. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-mochi-climb.png +0 -0
  92. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-mochi-walk.png +0 -0
  93. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-moss-climb.png +0 -0
  94. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-moss-walk.png +0 -0
  95. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-pip-climb.png +0 -0
  96. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/sprites/inkside-pip-walk.png +0 -0
  97. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/inkside/template.py +0 -0
  98. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/layered_playback.py +0 -0
  99. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/layered_renderer.py +0 -0
  100. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/light_toy.py +0 -0
  101. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/puppet_reactions.py +0 -0
  102. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/puppet_target.py +0 -0
  103. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/recovery.py +0 -0
  104. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pet/target_marker.py +0 -0
  105. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pinned/__init__.py +0 -0
  106. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pinned/live_ocr_widget.py +0 -0
  107. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/pinned/pinned_image.py +0 -0
  108. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/presentation/__init__.py +0 -0
  109. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/presentation/annotation_overlay.py +0 -0
  110. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/presentation/cursor_effects.py +0 -0
  111. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/presentation/keystroke_display.py +0 -0
  112. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/presentation/magnifier.py +0 -0
  113. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/reference/__init__.py +0 -0
  114. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/reference/image_compare.py +0 -0
  115. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/reference/reference_board.py +0 -0
  116. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/replica/__init__.py +0 -0
  117. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/replica/replica_widget.py +0 -0
  118. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/__init__.py +0 -0
  119. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/compositor_view.py +0 -0
  120. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/extend_graphic_scene.py +0 -0
  121. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/extend_graphic_view.py +0 -0
  122. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/math3d.py +0 -0
  123. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/media_frame.py +0 -0
  124. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/model_asset.py +0 -0
  125. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/render_session.py +0 -0
  126. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/renderer3d.py +0 -0
  127. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/runtime3d.py +0 -0
  128. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/scene.py +0 -0
  129. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/screen_topology.py +0 -0
  130. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/timeline.py +0 -0
  131. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/scene/view3d.py +0 -0
  132. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/screen_care/__init__.py +0 -0
  133. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/screen_care/color_vision_widget.py +0 -0
  134. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/screen_care/screen_filter.py +0 -0
  135. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/shortcuts/__init__.py +0 -0
  136. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/shortcuts/shortcut_sheet.py +0 -0
  137. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/sound_player/__init__.py +0 -0
  138. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/sound_player/sound_effect.py +0 -0
  139. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/sound_player/sound_player.py +0 -0
  140. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/spectrum/__init__.py +0 -0
  141. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/spectrum/spectrum_widget.py +0 -0
  142. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/text/__init__.py +0 -0
  143. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/text/draw_text.py +0 -0
  144. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/toast/__init__.py +0 -0
  145. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/toast/toast_widget.py +0 -0
  146. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/video/__init__.py +0 -0
  147. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/video/video_player.py +0 -0
  148. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/wallpaper/__init__.py +0 -0
  149. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/wallpaper/wallpaper_widget.py +0 -0
  150. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/web/__init__.py +0 -0
  151. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/web/webview.py +0 -0
  152. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/show/window_helpers.py +0 -0
  153. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/system_tray/__init__.py +0 -0
  154. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/system_tray/extend_system_tray.py +0 -0
  155. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/__init__.py +0 -0
  156. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/color/__init__.py +0 -0
  157. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/color/global_color.py +0 -0
  158. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/__init__.py +0 -0
  159. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/app_profile_dialog.py +0 -0
  160. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/asset_library_dialog.py +0 -0
  161. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/capture_editor.py +0 -0
  162. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/choose_file_dialog.py +0 -0
  163. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/clipboard_dialog.py +0 -0
  164. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/color_palette_dialog.py +0 -0
  165. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/command_palette_dialog.py +0 -0
  166. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/hotkey_settings_dialog.py +0 -0
  167. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/how_to_use_dialog.py +0 -0
  168. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/image_compare_dialog.py +0 -0
  169. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/image_history_dialog.py +0 -0
  170. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/monitor_profiles_dialog.py +0 -0
  171. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/pet_pack_editor.py +0 -0
  172. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/pet_pack_preview.py +0 -0
  173. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/pet_photo.py +0 -0
  174. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/pet_wardrobe.py +0 -0
  175. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/platform_capabilities_dialog.py +0 -0
  176. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/preset_schedule_dialog.py +0 -0
  177. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/preset_versions_dialog.py +0 -0
  178. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/reminder_dialog.py +0 -0
  179. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/remote_control_dialog.py +0 -0
  180. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/rules_dialog.py +0 -0
  181. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/scene_3d_animation_dialog.py +0 -0
  182. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/scene_action_dialog.py +0 -0
  183. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/scene_animation_dialog.py +0 -0
  184. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/scene_output_dialog.py +0 -0
  185. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/scene_templates_dialog.py +0 -0
  186. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/screen_privacy_dialog.py +0 -0
  187. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/screen_text_dialog.py +0 -0
  188. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/screensaver_dialog.py +0 -0
  189. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/signage_dialog.py +0 -0
  190. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/smart_pause_dialog.py +0 -0
  191. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/todo_dialog.py +0 -0
  192. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/usage_report_dialog.py +0 -0
  193. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/window_follow_dialog.py +0 -0
  194. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/window_pin_dialog.py +0 -0
  195. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/window_replica_dialog.py +0 -0
  196. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/dialog/workshop_dialog.py +0 -0
  197. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/main_ui.py +0 -0
  198. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/menu/__init__.py +0 -0
  199. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/menu/help_menu.py +0 -0
  200. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/menu/how_to_menu.py +0 -0
  201. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/menu/language_menu.py +0 -0
  202. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/menu/preset_menu.py +0 -0
  203. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/menu/settings_menu.py +0 -0
  204. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/nav/__init__.py +0 -0
  205. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/nav/sidebar.py +0 -0
  206. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/__init__.py +0 -0
  207. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/action_menu.py +0 -0
  208. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/control_center/__init__.py +0 -0
  209. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/control_center/control_center_ui.py +0 -0
  210. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/flow_layout.py +0 -0
  211. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/focus/__init__.py +0 -0
  212. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/focus/focus_setting_ui.py +0 -0
  213. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/gif/__init__.py +0 -0
  214. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/gif/gif_setting_ui.py +0 -0
  215. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/image/__init__.py +0 -0
  216. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/image/image_setting_ui.py +0 -0
  217. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/layout_kit.py +0 -0
  218. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/particle/__init__.py +0 -0
  219. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/particle/particle_setting_ui.py +0 -0
  220. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/pet/__init__.py +0 -0
  221. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/pet/pet_profile_controls.py +0 -0
  222. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/presentation/__init__.py +0 -0
  223. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/presentation/presentation_setting_ui.py +0 -0
  224. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/__init__.py +0 -0
  225. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_3d_editor.py +0 -0
  226. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_actions.py +0 -0
  227. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_manager.py +0 -0
  228. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_media_preview.py +0 -0
  229. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_page/__init__.py +0 -0
  230. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py +0 -0
  231. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_page/gif.py +0 -0
  232. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_page/image.py +0 -0
  233. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_page/puppet.py +0 -0
  234. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_page/registry.py +0 -0
  235. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_page/sound.py +0 -0
  236. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_page/text.py +0 -0
  237. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_page/video.py +0 -0
  238. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_page/web.py +0 -0
  239. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_setting_ui.py +0 -0
  240. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/scene_setting/scene_visual_editor.py +0 -0
  241. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/screen_care/__init__.py +0 -0
  242. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/screen_care/screen_care_setting_ui.py +0 -0
  243. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/sound_player/__init__.py +0 -0
  244. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/sound_player/sound_player_setting_ui.py +0 -0
  245. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/text/__init__.py +0 -0
  246. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/text/text_setting_ui.py +0 -0
  247. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/tools/__init__.py +0 -0
  248. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/tools/tools_setting_ui.py +0 -0
  249. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/utils.py +0 -0
  250. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/video/__init__.py +0 -0
  251. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/video/video_setting_ui.py +0 -0
  252. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/wallpaper/__init__.py +0 -0
  253. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/wallpaper/wallpaper_setting_ui.py +0 -0
  254. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/web/__init__.py +0 -0
  255. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/web/web_setting_ui.py +0 -0
  256. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/widgets/__init__.py +0 -0
  257. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/page/widgets/widgets_setting_ui.py +0 -0
  258. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/plugin_pages.py +0 -0
  259. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/style/__init__.py +0 -0
  260. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/ui/style/app_style.py +0 -0
  261. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/user_setting/__init__.py +0 -0
  262. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/user_setting/pet_profiles.py +0 -0
  263. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/user_setting/preset_history.py +0 -0
  264. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/user_setting/preset_repository.py +0 -0
  265. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/user_setting/scene_setting.py +0 -0
  266. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/user_setting/user_setting_file.py +0 -0
  267. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/__init__.py +0 -0
  268. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/actions/__init__.py +0 -0
  269. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/actions/action_registry.py +0 -0
  270. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/actions/command_history.py +0 -0
  271. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/actions/deferred_action.py +0 -0
  272. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/app_profile/__init__.py +0 -0
  273. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/app_profile/app_profile_service.py +0 -0
  274. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/asset_library/__init__.py +0 -0
  275. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/asset_library/file_lock.py +0 -0
  276. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/asset_library/inspect.py +0 -0
  277. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/asset_library/references.py +0 -0
  278. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/asset_library/repository.py +0 -0
  279. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/asset_library/service.py +0 -0
  280. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/audio_meter/__init__.py +0 -0
  281. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/audio_meter/audio_envelope.py +0 -0
  282. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/audio_meter/loopback_capture.py +0 -0
  283. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/audio_meter/microphone_meter.py +0 -0
  284. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/audio_meter/screen_audio.py +0 -0
  285. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/audio_meter/spectrum_analyzer.py +0 -0
  286. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/audio_meter/system_audio_meter.py +0 -0
  287. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/autostart/__init__.py +0 -0
  288. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/autostart/autostart_service.py +0 -0
  289. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/break_reminder/__init__.py +0 -0
  290. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/break_reminder/break_reminder.py +0 -0
  291. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/browser/__init__.py +0 -0
  292. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/browser/browser.py +0 -0
  293. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/capture_editor/__init__.py +0 -0
  294. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/capture_editor/document.py +0 -0
  295. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/clipboard/__init__.py +0 -0
  296. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/clipboard/clipboard_history.py +0 -0
  297. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/clipboard/clipboard_watcher.py +0 -0
  298. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/color_vision/__init__.py +0 -0
  299. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/color_vision/color_vision.py +0 -0
  300. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/critical_exit/__init__.py +0 -0
  301. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/critical_exit/check_key_is_press.py +0 -0
  302. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/critical_exit/critical_exit.py +0 -0
  303. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/critical_exit/win32_vk.py +0 -0
  304. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/exception/__init__.py +0 -0
  305. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/exception/exception_tags.py +0 -0
  306. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/exception/exceptions.py +0 -0
  307. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/focus_shield/__init__.py +0 -0
  308. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/focus_shield/focus_shield.py +0 -0
  309. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/focus_timer/__init__.py +0 -0
  310. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/focus_timer/focus_timer.py +0 -0
  311. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/hotkey/__init__.py +0 -0
  312. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/hotkey/hotkey_service.py +0 -0
  313. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/image_history/__init__.py +0 -0
  314. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/image_history/capture_service.py +0 -0
  315. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/image_history/repository.py +0 -0
  316. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/image_history/service.py +0 -0
  317. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/imervue/__init__.py +0 -0
  318. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/imervue/puppet_asset.py +0 -0
  319. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/imervue/runtime.py +0 -0
  320. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/input_watch/__init__.py +0 -0
  321. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/input_watch/input_watch_service.py +0 -0
  322. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/input_watch/typing_watch.py +0 -0
  323. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/json/__init__.py +0 -0
  324. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/json/json_file.py +0 -0
  325. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/json/json_repository.py +0 -0
  326. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/keep_awake/__init__.py +0 -0
  327. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/keep_awake/keep_awake.py +0 -0
  328. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/linux/__init__.py +0 -0
  329. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/linux/audio.py +0 -0
  330. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/linux/capabilities.py +0 -0
  331. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/linux/windows.py +0 -0
  332. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/logging/__init__.py +0 -0
  333. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/logging/loggin_instance.py +0 -0
  334. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/macos/__init__.py +0 -0
  335. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/macos/audio.py +0 -0
  336. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/macos/backend.py +0 -0
  337. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/macos/capture.py +0 -0
  338. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/macos/input.py +0 -0
  339. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/macos/midi.py +0 -0
  340. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/macos/region_capture.py +0 -0
  341. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/measure/__init__.py +0 -0
  342. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/measure/color_palette.py +0 -0
  343. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/measure/measure.py +0 -0
  344. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/media_keys/__init__.py +0 -0
  345. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/media_keys/media_keys.py +0 -0
  346. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/midi/__init__.py +0 -0
  347. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/midi/midi_input.py +0 -0
  348. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/multi_language/__init__.py +0 -0
  349. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/multi_language/language_wrapper.py +0 -0
  350. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/multi_language/retranslate.py +0 -0
  351. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/multi_language/scene_3d_words.py +0 -0
  352. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/now_playing/__init__.py +0 -0
  353. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/now_playing/now_playing.py +0 -0
  354. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/pet_chat/__init__.py +0 -0
  355. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/pet_chat/pet_chat_service.py +0 -0
  356. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/pet_companion/__init__.py +0 -0
  357. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/pet_companion/companion.py +0 -0
  358. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/pet_companion/petting.py +0 -0
  359. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/pet_companion/stats.py +0 -0
  360. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/pet_pack/__init__.py +0 -0
  361. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/pet_pack/layered.py +0 -0
  362. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/pet_pack/pack_builder.py +0 -0
  363. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/pet_pack/palette.py +0 -0
  364. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/pet_pack/variants.py +0 -0
  365. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/platform_info/__init__.py +0 -0
  366. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/platform_info/capabilities.py +0 -0
  367. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/platform_info/platform_info.py +0 -0
  368. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/playlist/__init__.py +0 -0
  369. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/playlist/playlist.py +0 -0
  370. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/plugins/__init__.py +0 -0
  371. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/plugins/plugin_loader.py +0 -0
  372. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/plugins/plugin_manifest.py +0 -0
  373. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/power_mode/__init__.py +0 -0
  374. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/power_mode/power_mode.py +0 -0
  375. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/preset_schedule/__init__.py +0 -0
  376. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/preset_schedule/preset_schedule_service.py +0 -0
  377. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/recording/__init__.py +0 -0
  378. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/recording/avi_writer.py +0 -0
  379. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/recording/frame_recorder.py +0 -0
  380. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/recording/gif_writer.py +0 -0
  381. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/redirect_manager/__init__.py +0 -0
  382. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/redirect_manager/redirect_manager_class.py +0 -0
  383. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/reminder/__init__.py +0 -0
  384. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/reminder/reminder_service.py +0 -0
  385. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/remote/__init__.py +0 -0
  386. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/remote/remote_server.py +0 -0
  387. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/remote/tls_certificate.py +0 -0
  388. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/rules/__init__.py +0 -0
  389. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/rules/rule_engine.py +0 -0
  390. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/__init__.py +0 -0
  391. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_3d_acceptance.py +0 -0
  392. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_3d_camera_acceptance.py +0 -0
  393. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_3d_document.py +0 -0
  394. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_3d_fixtures.py +0 -0
  395. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_3d_media_acceptance.py +0 -0
  396. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_3d_stress.py +0 -0
  397. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_3d_templates.py +0 -0
  398. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_3d_verification.py +0 -0
  399. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_action_values.py +0 -0
  400. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_animation.py +0 -0
  401. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_document.py +0 -0
  402. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_editor_document.py +0 -0
  403. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_package.py +0 -0
  404. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_resource_reads.py +0 -0
  405. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_source.py +0 -0
  406. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/scene_format/scene_templates.py +0 -0
  407. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/screen_privacy/__init__.py +0 -0
  408. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/screen_privacy/capture_affinity.py +0 -0
  409. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/screen_privacy/share_watch.py +0 -0
  410. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/screen_text/__init__.py +0 -0
  411. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/screen_text/live_ocr.py +0 -0
  412. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/screen_text/local_ocr.py +0 -0
  413. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/screen_text/screen_text_service.py +0 -0
  414. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/screensaver/__init__.py +0 -0
  415. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/screensaver/screensaver_service.py +0 -0
  416. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/shutdown_barrier.py +0 -0
  417. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/signage/__init__.py +0 -0
  418. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/signage/signage_service.py +0 -0
  419. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/smart_pause/__init__.py +0 -0
  420. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/smart_pause/pause_rules.py +0 -0
  421. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/smart_pause/smart_pause_service.py +0 -0
  422. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/steam/__init__.py +0 -0
  423. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/steam/steam_language.py +0 -0
  424. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/steam/steam_runtime.py +0 -0
  425. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/system_stats/__init__.py +0 -0
  426. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/system_stats/system_stats.py +0 -0
  427. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/text_source/__init__.py +0 -0
  428. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/text_source/local_file_source.py +0 -0
  429. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/text_source/text_source.py +0 -0
  430. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/theme_schedule/__init__.py +0 -0
  431. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/theme_schedule/theme_schedule_service.py +0 -0
  432. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/todo/__init__.py +0 -0
  433. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/todo/calendar_import.py +0 -0
  434. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/todo/repository.py +0 -0
  435. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/todo/service.py +0 -0
  436. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/usage_tracking/__init__.py +0 -0
  437. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/usage_tracking/usage_service.py +0 -0
  438. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/usage_tracking/usage_tracker.py +0 -0
  439. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/virtual_camera/__init__.py +0 -0
  440. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/virtual_camera/camera_feed.py +0 -0
  441. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/virtual_camera/frame_sender.py +0 -0
  442. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/virtual_camera/virtual_camera.py +0 -0
  443. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/virtual_desktop/__init__.py +0 -0
  444. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/virtual_desktop/virtual_desktop.py +0 -0
  445. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/weather/__init__.py +0 -0
  446. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/weather/weather_service.py +0 -0
  447. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/web_url.py +0 -0
  448. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/whiteboard/__init__.py +0 -0
  449. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/whiteboard/document.py +0 -0
  450. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/whiteboard/raster.py +0 -0
  451. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/window_pin/__init__.py +0 -0
  452. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/window_pin/follow_window.py +0 -0
  453. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/window_pin/monitor_move.py +0 -0
  454. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/window_pin/topology_profiles.py +0 -0
  455. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/window_pin/window_layout.py +0 -0
  456. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/window_pin/window_pin.py +0 -0
  457. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/window_replica/__init__.py +0 -0
  458. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/window_replica/dwm_thumbnail.py +0 -0
  459. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/workshop/__init__.py +0 -0
  460. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/workshop/workshop_cache.py +0 -0
  461. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/workshop/workshop_content.py +0 -0
  462. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/workshop/workshop_jobs.py +0 -0
  463. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/workshop/workshop_manifest.py +0 -0
  464. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/workshop/workshop_package.py +0 -0
  465. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/workshop/workshop_publications.py +0 -0
  466. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/workshop/workshop_publisher.py +0 -0
  467. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/workshop/workshop_service.py +0 -0
  468. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine/utils/workshop/workshop_subscriptions.py +0 -0
  469. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine.egg-info/dependency_links.txt +0 -0
  470. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine.egg-info/entry_points.txt +0 -0
  471. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine.egg-info/requires.txt +0 -0
  472. {frontengine-1.0.83 → frontengine-1.0.85}/frontengine.egg-info/top_level.txt +0 -0
  473. {frontengine-1.0.83 → frontengine-1.0.85}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frontengine
3
- Version: 1.0.83
3
+ Version: 1.0.85
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/JeffreyChen-SteamProjects/FrontEngine
@@ -422,6 +422,10 @@ Screen text: Tools → Read text first uses local OCR: Windows.Media.Ocr on Wind
422
422
 
423
423
  Puppet pets: install the optional puppet extra and an available Imervue runtime, then choose an original Imervue .puppet v1 file on the Pet page or drop it there. Existing image/sprite pet packs still work. Puppet pets use Imervue's canvas, motions and expressions, can be cloned or closed, and participate in FrontEngine's overlay controls and presets. Choose an optional .petscript.json for Imervue's existing script engine; do not treat FrontEngine pet.json packs as puppet files. Unknown versions, unsafe archive paths and invalid assets are rejected before runtime loading.
424
424
 
425
+ Puppet pets also stroll on their own: after a few seconds' rest they walk a short way left or right along their current height with the walk motion, stay inside the screen's work area, then rest again. A stroll gives way to dragging, petting, Come here and toys, settling while typing, and modes that do not allow acting alone.
426
+
427
+ The Behaviour menu's default, Cycle all actions (random), has a free pet pick what to do next at random from its whole set of actions; Walk on floor keeps only walking and idling. A sprite pet chooses among walking, idling, sitting, playing, grooming, climbing the nearer wall, waving, sleeping, celebrating and showing off its outfit; a Puppet pet chooses between a stroll and sitting, playing, grooming, waving or celebrating in place. A summoned pet sets off walking at once. Poses are held in place, and a pet without an image for a pose shows its idle image.
428
+
425
429
  Scenes: the Scene page accepts old entry-mapping JSON, a versioned frontengine.scene envelope, and portable .fescene packages. Add a PUPPET entry with position, size, opacity, finite numeric parameters, optional motion, expression and script. Paths in JSON resolve relative to the scene file. A .fescene includes the referenced media, original .puppet and optional .petscript.json so it can move between machines. Import checks paths, symlinks, versions and extraction limits. A FrontEngine scene remains a scene package; .puppet remains one Imervue character.
426
430
 
427
431
  macOS: the optional macos extra targets macOS 13+ with public PyObjC frameworks. Backends provide ScreenCaptureKit screen/window capture and system audio, microphone capture, Quartz window geometry, Accessibility window layout/movement, CoreMIDI, media keys and the F12 exit path. Screen Recording, Accessibility and Microphone permissions are checked separately; follow System Settings → Privacy & Security and restart when requested. Foreign-window opacity/topmost changes, Space selection and excluding overlays from other apps' captures remain unavailable. Native macOS permissions, hardware and performance have not been verified on this Windows development host. Settings → macOS permissions and capabilities lists each feature as available, unavailable or unsupported and shows the permission or installation reason.
@@ -482,6 +486,7 @@ it can be tested with a fake one.
482
486
  pull request, all CI checks green.
483
487
  - **Building the Windows executable** — `python exe/build_exe.py`
484
488
  (Nuitka; add `--onefile` for a single file).
489
+ It compiles on every CPU core by default; `--jobs N` caps the parallel jobs (less memory), `--jobs -N` leaves N cores free.
485
490
  - **Documentation** — Sphinx sources in `docs/`, published to
486
491
  [Read the Docs](https://frontengine.readthedocs.io/en/latest/) in all seven
487
492
  languages.
@@ -615,6 +620,8 @@ Customize pet also sets Chatter (Off, Rarely, Normal, Often) for lines the pet s
615
620
 
616
621
  The pet manager's interaction list also offers the selected live pet's own menu commands: photo, status, reminder, chat when a chat service is attached, clone and close, plus every motion and expression of a Puppet model. Everything in a pet's right-click menu can therefore be done with the keyboard.
617
622
 
623
+ Use built-in character on the Pet page installs the chosen INKSIDE character and its wardrobe in the background and selects it as the source. Start then spawns an ordinary sprite pet wearing that character: it walks and climbs with the hand-drawn step frames, can be dressed in the wardrobe, and keeps its outfit when it already wears the character. Use built-in Puppet model beside it still makes the Imervue Puppet version.
624
+
618
625
  Use built-in Puppet model on the Pet page draws the chosen INKSIDE character as an Imervue .puppet model in the background: rigged head, arms, tail and body, ten motions, three expressions and a pet script that maps companion actions to them. It is saved under pet-assets/puppets and selected as the source with its script, so Start spawns it as a Puppet pet.
619
626
 
620
627
  On setups with several monitors at different scaling, a pet dragged or brought back to another monitor keeps its size, stays inside that monitor’s work area and walks there. Window ledges on scaled monitors are measured in the same coordinates as the pet, so it perches exactly on top of windows.
@@ -371,6 +371,10 @@ Screen text: Tools → Read text first uses local OCR: Windows.Media.Ocr on Wind
371
371
 
372
372
  Puppet pets: install the optional puppet extra and an available Imervue runtime, then choose an original Imervue .puppet v1 file on the Pet page or drop it there. Existing image/sprite pet packs still work. Puppet pets use Imervue's canvas, motions and expressions, can be cloned or closed, and participate in FrontEngine's overlay controls and presets. Choose an optional .petscript.json for Imervue's existing script engine; do not treat FrontEngine pet.json packs as puppet files. Unknown versions, unsafe archive paths and invalid assets are rejected before runtime loading.
373
373
 
374
+ Puppet pets also stroll on their own: after a few seconds' rest they walk a short way left or right along their current height with the walk motion, stay inside the screen's work area, then rest again. A stroll gives way to dragging, petting, Come here and toys, settling while typing, and modes that do not allow acting alone.
375
+
376
+ The Behaviour menu's default, Cycle all actions (random), has a free pet pick what to do next at random from its whole set of actions; Walk on floor keeps only walking and idling. A sprite pet chooses among walking, idling, sitting, playing, grooming, climbing the nearer wall, waving, sleeping, celebrating and showing off its outfit; a Puppet pet chooses between a stroll and sitting, playing, grooming, waving or celebrating in place. A summoned pet sets off walking at once. Poses are held in place, and a pet without an image for a pose shows its idle image.
377
+
374
378
  Scenes: the Scene page accepts old entry-mapping JSON, a versioned frontengine.scene envelope, and portable .fescene packages. Add a PUPPET entry with position, size, opacity, finite numeric parameters, optional motion, expression and script. Paths in JSON resolve relative to the scene file. A .fescene includes the referenced media, original .puppet and optional .petscript.json so it can move between machines. Import checks paths, symlinks, versions and extraction limits. A FrontEngine scene remains a scene package; .puppet remains one Imervue character.
375
379
 
376
380
  macOS: the optional macos extra targets macOS 13+ with public PyObjC frameworks. Backends provide ScreenCaptureKit screen/window capture and system audio, microphone capture, Quartz window geometry, Accessibility window layout/movement, CoreMIDI, media keys and the F12 exit path. Screen Recording, Accessibility and Microphone permissions are checked separately; follow System Settings → Privacy & Security and restart when requested. Foreign-window opacity/topmost changes, Space selection and excluding overlays from other apps' captures remain unavailable. Native macOS permissions, hardware and performance have not been verified on this Windows development host. Settings → macOS permissions and capabilities lists each feature as available, unavailable or unsupported and shows the permission or installation reason.
@@ -431,6 +435,7 @@ it can be tested with a fake one.
431
435
  pull request, all CI checks green.
432
436
  - **Building the Windows executable** — `python exe/build_exe.py`
433
437
  (Nuitka; add `--onefile` for a single file).
438
+ It compiles on every CPU core by default; `--jobs N` caps the parallel jobs (less memory), `--jobs -N` leaves N cores free.
434
439
  - **Documentation** — Sphinx sources in `docs/`, published to
435
440
  [Read the Docs](https://frontengine.readthedocs.io/en/latest/) in all seven
436
441
  languages.
@@ -564,6 +569,8 @@ Customize pet also sets Chatter (Off, Rarely, Normal, Often) for lines the pet s
564
569
 
565
570
  The pet manager's interaction list also offers the selected live pet's own menu commands: photo, status, reminder, chat when a chat service is attached, clone and close, plus every motion and expression of a Puppet model. Everything in a pet's right-click menu can therefore be done with the keyboard.
566
571
 
572
+ Use built-in character on the Pet page installs the chosen INKSIDE character and its wardrobe in the background and selects it as the source. Start then spawns an ordinary sprite pet wearing that character: it walks and climbs with the hand-drawn step frames, can be dressed in the wardrobe, and keeps its outfit when it already wears the character. Use built-in Puppet model beside it still makes the Imervue Puppet version.
573
+
567
574
  Use built-in Puppet model on the Pet page draws the chosen INKSIDE character as an Imervue .puppet model in the background: rigged head, arms, tail and body, ten motions, three expressions and a pet script that maps companion actions to them. It is saved under pet-assets/puppets and selected as the source with its script, so Start spawns it as a Puppet pet.
568
575
 
569
576
  On setups with several monitors at different scaling, a pet dragged or brought back to another monitor keeps its size, stays inside that monitor’s work area and walks there. Window ledges on scaled monitors are measured in the same coordinates as the pet, so it perches exactly on top of windows.
@@ -48,6 +48,7 @@ from frontengine.utils.multi_language.language_wrapper import language_wrapper
48
48
  BEHAVIOUR_FLOOR = "floor" # walk on the floor with gravity, throw & bounce
49
49
  BEHAVIOUR_WANDER = "wander" # free 2D bounce, no gravity
50
50
  BEHAVIOUR_CHASE = "chase" # chase the mouse cursor, sleep when caught
51
+ BEHAVIOUR_ACTIONS = "actions" # floor mode cycling through every action at random (default)
51
52
 
52
53
  # 攀爬時所在的表面 / Surface the pet is crawling on while climbing
53
54
  SURFACE_FLOOR = "floor"
@@ -87,10 +88,21 @@ _STATE_FALLBACKS = {
87
88
  STATE_FALL: (STATE_WALK,),
88
89
  STATE_DRAG: (STATE_WALK,),
89
90
  **{action: (STATE_IDLE, STATE_WALK) for action in ("greet", "pet", "groom", "feed", "play", "sit",
90
- "land", "catch", "peer_greet", "wake")},
91
+ "land", "catch", "peer_greet", "wake",
92
+ "celebrate", "outfit_show")},
91
93
  "sleep_in": (STATE_SLEEP, STATE_IDLE, STATE_WALK),
92
94
  }
93
95
 
96
+ # What a free pet does on its own, picked at random whenever its current state ends:
97
+ # (state, weight, min ticks, max ticks) at 33 ms per tick. "climb" walks to the nearer
98
+ # wall and climbs it; the poses are held in place, and groom lasts its 3 s animation.
99
+ AUTONOMOUS_ACTIONS = (
100
+ ("walk", 34, 30, 120), ("idle", 14, 20, 80), ("sit", 10, 60, 150), ("play", 8, 45, 90),
101
+ ("groom", 7, 91, 91), ("climb", 6, 0, 0), ("greet", 5, 30, 55), ("sleep", 5, 120, 300),
102
+ ("celebrate", 4, 30, 60), ("outfit_show", 3, 45, 75),
103
+ )
104
+ POSE_STATES = frozenset(("sit", "play", "groom", "greet", "celebrate", "outfit_show"))
105
+
94
106
  # Short physical reactions shown over autonomous movement (milliseconds). They are
95
107
  # purely visual, so they never block toys, social play or user commands.
96
108
  _FLASH_MS = {"land": 280, "catch": 580, "peer_greet": 1600}
@@ -267,6 +279,8 @@ def derive_visual_state(dragging: bool, airborne: bool, surface: str, motion_sta
267
279
  return STATE_SLEEP
268
280
  if surface == SURFACE_FLOOR and motion_state == "idle":
269
281
  return STATE_IDLE
282
+ if surface == SURFACE_FLOOR and motion_state in POSE_STATES:
283
+ return motion_state
270
284
  return STATE_WALK
271
285
 
272
286
 
@@ -642,7 +656,7 @@ class PetMotion:
642
656
  self.height = int(height)
643
657
  self.bounds = bounds # (left, top, right, bottom)
644
658
  self.speed = max(1, int(speed))
645
- self.behaviour = behaviour
659
+ self.behaviour = behaviour # property: BEHAVIOUR_ACTIONS becomes floor + random_actions
646
660
  self._rng = rng if rng is not None else _random_module.SystemRandom()
647
661
  self.vx = float(self.speed)
648
662
  self.vy = 0.0 if behaviour != BEHAVIOUR_WANDER else float(self.speed)
@@ -652,8 +666,9 @@ class PetMotion:
652
666
  # 打字時安分下來:True 的時候 step() 原地不動。
653
667
  # Settled while typing: step() stays put while this is True.
654
668
  self.settled = False
655
- self.state = "walk" # walk | idle | sleep
669
+ self.state = "walk" # walk | idle | sleep | one of POSE_STATES
656
670
  self._state_ticks = 0
671
+ self._seek_wall = False # walking to the nearer wall to climb it
657
672
  self._idle_count = 0
658
673
  self.target: Optional[Tuple[float, float]] = None
659
674
  self.asleep = False
@@ -672,6 +687,21 @@ class PetMotion:
672
687
  # game); it takes precedence over each mode's own default movement.
673
688
  self.guidance: Optional[Tuple[float, float]] = None
674
689
 
690
+ @property
691
+ def behaviour(self) -> str:
692
+ return self._behaviour
693
+
694
+ @behaviour.setter
695
+ def behaviour(self, value: str) -> None:
696
+ """BEHAVIOUR_ACTIONS is the floor mode with every action picked at random, so floor checks hold."""
697
+ self.random_actions = value == BEHAVIOUR_ACTIONS
698
+ self._behaviour = BEHAVIOUR_FLOOR if self.random_actions else value
699
+
700
+ @property
701
+ def mode(self) -> str:
702
+ """The behaviour as chosen, BEHAVIOUR_ACTIONS included; use this when saving or showing it."""
703
+ return BEHAVIOUR_ACTIONS if self.random_actions else self._behaviour
704
+
675
705
  @property
676
706
  def facing_left(self) -> bool:
677
707
  return self.vx < 0
@@ -822,7 +852,8 @@ class PetMotion:
822
852
 
823
853
  def _turn_or_climb(self, wall: str, turned_vx: float) -> None:
824
854
  """走到邊緣了:抓上牆去爬,或是掉頭往回走。"""
825
- if self.climb and self._rng.random() < self.CLIMB_CHANCE:
855
+ if self.climb and (self._seek_wall or self._rng.random() < self.CLIMB_CHANCE):
856
+ self._seek_wall = False
826
857
  self.surface = wall
827
858
  self.vy = float(-self.speed)
828
859
  else:
@@ -1001,17 +1032,42 @@ class PetMotion:
1001
1032
  self.vy = float(self.speed)
1002
1033
 
1003
1034
  def _new_state(self, force_walk: bool = False) -> None:
1004
- if force_walk or self._rng.random() < 0.65:
1005
- self.state = "walk"
1006
- self._idle_count = 0
1007
- if not force_walk:
1008
- self.vx = float(self.speed) if self._rng.random() < 0.5 else float(-self.speed)
1035
+ """Pick what to do next: walk or idle, or anything from AUTONOMOUS_ACTIONS in random-actions mode."""
1036
+ self._seek_wall = False
1037
+ if force_walk:
1038
+ self.state, self._idle_count = "walk", 0
1009
1039
  self._state_ticks = self._rng.randint(30, 120)
1010
- elif self._idle_count >= 2:
1040
+ return
1041
+ if self._idle_count >= 2:
1011
1042
  # been idling a while -> doze off
1012
- self.state = STATE_SLEEP
1013
- self._idle_count = 0
1043
+ self.state, self._idle_count = STATE_SLEEP, 0
1014
1044
  self._state_ticks = self._rng.randint(120, 300)
1045
+ return
1046
+ if not self.random_actions:
1047
+ self._walk_or_idle()
1048
+ return
1049
+ options = [entry for entry in AUTONOMOUS_ACTIONS
1050
+ if entry[0] != STATE_CLIMB or (self.climb and not self.on_platform)]
1051
+ name, _weight, low, high = self._rng.choices(options, weights=[entry[1] for entry in options])[0]
1052
+ self._idle_count = self._idle_count + 1 if name == "idle" else 0
1053
+ if name == STATE_CLIMB:
1054
+ left, _top, right, _bottom = self.bounds
1055
+ toward_left = self.x - left <= right - (self.x + self.width)
1056
+ self.state, self._seek_wall = "walk", True
1057
+ self.vx = float(-self.speed) if toward_left else float(self.speed)
1058
+ self._state_ticks = 10 ** 6 # until the wall is reached
1059
+ return
1060
+ self.state = name
1061
+ if name == "walk":
1062
+ self.vx = float(self.speed) if self._rng.random() < 0.5 else float(-self.speed)
1063
+ self._state_ticks = self._rng.randint(low, high)
1064
+
1065
+ def _walk_or_idle(self) -> None:
1066
+ """The plain floor mode: mostly walking, sometimes idling."""
1067
+ if self._rng.random() < 0.65:
1068
+ self.state, self._idle_count = "walk", 0
1069
+ self.vx = float(self.speed) if self._rng.random() < 0.5 else float(-self.speed)
1070
+ self._state_ticks = self._rng.randint(30, 120)
1015
1071
  else:
1016
1072
  self.state = "idle"
1017
1073
  self._idle_count += 1
@@ -1250,7 +1306,7 @@ class DesktopPetWidget(BaseWidget):
1250
1306
  self.menu.addAction(self.photo_action)
1251
1307
  self._presentation_defaults = {
1252
1308
  "size": min(512, self._base_size), "speed": max(1, min(20, int(self.motion.speed))),
1253
- "behaviour": self.motion.behaviour, "climb": bool(self.motion.climb),
1309
+ "behaviour": self.motion.mode, "climb": bool(self.motion.climb),
1254
1310
  "sit_on_windows": self._sit_on_windows, "speech_bubbles": self._talk,
1255
1311
  "volume": int(self._volume * 100), "settle_typing": False,
1256
1312
  "chatter": "normal", "motion": "normal",
@@ -1592,6 +1648,8 @@ class DesktopPetWidget(BaseWidget):
1592
1648
  self.motion.x = float(left)
1593
1649
  self.motion.y = float(bottom - self.pet_size)
1594
1650
  self.move(int(self.motion.x), int(self.motion.y))
1651
+ # A freshly summoned pet sets off walking at once instead of rolling its first action.
1652
+ self.motion.wake()
1595
1653
  self._tick_interval_ms = max(10, int(interval_ms))
1596
1654
  self._timer.start(scaled_interval(self._tick_interval_ms, self._low_power))
1597
1655
  self._schedule_chatter()
@@ -1889,7 +1947,7 @@ class DesktopPetWidget(BaseWidget):
1889
1947
  if action.get("status"):
1890
1948
  self.show_status()
1891
1949
  behaviour = action.get("behaviour")
1892
- if behaviour in (BEHAVIOUR_FLOOR, BEHAVIOUR_WANDER, BEHAVIOUR_CHASE):
1950
+ if behaviour in (BEHAVIOUR_FLOOR, BEHAVIOUR_ACTIONS, BEHAVIOUR_WANDER, BEHAVIOUR_CHASE):
1893
1951
  self.motion.behaviour = behaviour
1894
1952
 
1895
1953
  def _check_reminders(self) -> None:
@@ -125,7 +125,7 @@ class PetProfileSession(QObject):
125
125
  self.changed.emit()
126
126
  return True
127
127
 
128
- def apply_appearance(self, expected: dict, candidate: dict, prepared=None) -> None:
128
+ def apply_appearance(self, expected: dict, candidate: dict, prepared=None, present: bool = True) -> None:
129
129
  """Persist a prevalidated/preloaded wardrobe draft without stale overwrites."""
130
130
  if self._closed:
131
131
  raise ValueError("Pet session is closed")
@@ -134,7 +134,7 @@ class PetProfileSession(QObject):
134
134
  raise ValueError("Pet appearance changed while previewing")
135
135
  self.profiles.update(self.identifier, {**self.companion.snapshot(), "appearance": candidate})
136
136
  self.appearance_renderer = prepared
137
- if candidate != expected:
137
+ if present and candidate != expected:
138
138
  self.companion.present('outfit_show')
139
139
  self.changed.emit()
140
140
 
@@ -17,6 +17,7 @@ from frontengine.utils.multi_language.retranslate import translate
17
17
  from frontengine.show.pet.companion_menu import add_companion_actions, add_food_actions, companion_status
18
18
  from frontengine.show.pet.puppet_reactions import PuppetReactions, load_reactions
19
19
  from frontengine.utils.pet_companion.petting import PettingGesture
20
+ from frontengine.show.pet.puppet_stroll import PuppetStroll
20
21
  from frontengine.show.pet.puppet_target import PuppetTargetController
21
22
 
22
23
 
@@ -56,6 +57,7 @@ class PuppetPetWidget(DraggableTopWindow):
56
57
  self._follows_screen = False
57
58
  self._petting_revision = None
58
59
  self._target = PuppetTargetController(self)
60
+ self._stroll = PuppetStroll(self)
59
61
  self.placement_revision = 0
60
62
  self._talk = True
61
63
  self._initial_size = size
@@ -221,15 +223,24 @@ class PuppetPetWidget(DraggableTopWindow):
221
223
  if settled:
222
224
  self.stop_toy()
223
225
  self._end_petting()
224
- self.idle.set_enabled(self.isVisible() and not settled
226
+ self._stroll.stop()
227
+ elif self.isVisible() and not self._closed:
228
+ self._stroll.start()
229
+ self._show_activity()
230
+
231
+ def _show_activity(self) -> None:
232
+ """Idle, walk or the companion's action, from what is currently moving the pet."""
233
+ moving = self._target.marker is not None or self._stroll.walking
234
+ acting = self._stroll.acting if self._target.marker is None else None
235
+ self.idle.set_enabled(self.isVisible() and not self._settled
225
236
  and self._petting is None
226
- and self._target.marker is None
237
+ and not moving and acting is None
227
238
  and self.profile_session.companion.allows_autonomy)
228
- if settled:
239
+ if self._settled:
229
240
  self.reactions.reset()
230
241
  self.player.stop()
231
242
  elif self.isVisible():
232
- self.reactions.update('walk' if self._target.marker is not None else self.profile_session.companion.visual_action)
243
+ self.reactions.update('walk' if moving else acting or self.profile_session.companion.visual_action)
233
244
 
234
245
  def contextMenuEvent(self, event) -> None:
235
246
  words = language_wrapper.language_word_dict
@@ -483,6 +494,8 @@ class PuppetPetWidget(DraggableTopWindow):
483
494
  handle.screenChanged.connect(lambda _screen: QTimer.singleShot(0, self, self._follow_screen))
484
495
  if not self._closed:
485
496
  self.profile_session.resume()
497
+ if not self._welcomed and not self._settled:
498
+ self._stroll.start(soon=True) # a summoned pet sets off at once
486
499
  self.set_settled(self._settled)
487
500
  self.script_timer.start()
488
501
  if not self._welcomed:
@@ -493,6 +506,7 @@ class PuppetPetWidget(DraggableTopWindow):
493
506
  def hideEvent(self, event) -> None:
494
507
  if not self._closed:
495
508
  self.stop_toy()
509
+ self._stroll.stop()
496
510
  self._end_petting()
497
511
  self.reactions.reset()
498
512
  self.profile_session.pause()
@@ -510,6 +524,7 @@ class PuppetPetWidget(DraggableTopWindow):
510
524
  return False
511
525
  self._closed = True
512
526
  self.stop_toy()
527
+ self._stroll.stop()
513
528
  self._end_petting()
514
529
  self.reactions.reset()
515
530
  self.script_timer.stop()
@@ -0,0 +1,132 @@
1
+ """Autonomous behaviour for Puppet pets: after each rest, a short walk or a random action."""
2
+ from __future__ import annotations
3
+
4
+ import random
5
+ from time import monotonic
6
+
7
+ from PySide6.QtCore import QObject, QTimer
8
+
9
+
10
+ class PuppetStroll(QObject):
11
+ """Now and then walk the pet left or right, or play a random action in place.
12
+
13
+ It yields to everything that already owns the pet: dragging, petting, a call or
14
+ toy target, settling while typing and companion modes without autonomy. The
15
+ pet ends every walk inside its screen's work area.
16
+ """
17
+
18
+ SPEED = 70.0 # pixels per second
19
+ REST_SECONDS = (3.0, 8.0)
20
+ DISTANCE = (120, 420) # pixels per walk
21
+ # What the pet does after each rest, picked at random: (action, weight).
22
+ CHOICES = (('walk', 50), ('sit', 12), ('play', 10), ('groom', 9), ('greet', 10), ('celebrate', 9))
23
+ HOLD_SECONDS = {'groom': (3.0, 3.0)} # others hold 2-4 s
24
+
25
+ def __init__(self, pet, rng: random.Random | None = None) -> None:
26
+ super().__init__(pet)
27
+ self.pet = pet
28
+ self.rng = rng or random.Random() # nosec B311 - stroll timing and distance only, not security
29
+ self.walking = False
30
+ self.acting: str | None = None # action played in place
31
+ self._walk_next = False # a newly summoned pet walks off first
32
+ self._hold = 0.0
33
+ self.target_x: int | None = None
34
+ self._x = 0.0
35
+ self._last = monotonic()
36
+ self._rest = QTimer(self)
37
+ self._rest.setSingleShot(True)
38
+ self._rest.timeout.connect(self._begin)
39
+ self._step = QTimer(self)
40
+ self._step.setInterval(33)
41
+ self._step.timeout.connect(self.tick)
42
+
43
+ def _free(self) -> bool:
44
+ return self.pet.can_play_with_toy and self.pet._target.marker is None
45
+
46
+ def _span(self) -> tuple[int, int] | None:
47
+ screen = self.pet.screen()
48
+ if screen is None:
49
+ return None
50
+ area = screen.availableGeometry()
51
+ left, right = area.left(), area.right() + 1 - self.pet.width()
52
+ return (left, right) if right > left else None
53
+
54
+ def start(self, soon: bool = False) -> None:
55
+ """Schedule the next walk or action unless one is already waiting or under way.
56
+
57
+ ``soon`` is for a pet that was just summoned: it sets off walking almost at once.
58
+ """
59
+ if not self.walking and self.acting is None and not self._rest.isActive():
60
+ self._walk_next = soon
61
+ self._rest.start(300 if soon else round(1000 * self.rng.uniform(*self.REST_SECONDS)))
62
+
63
+ def stop(self) -> None:
64
+ """Stop walking, acting and waiting; nothing resumes until start() is called."""
65
+ self._rest.stop()
66
+ self._step.stop()
67
+ if self.walking or self.acting is not None:
68
+ self.walking, self.acting, self.target_x = False, None, None
69
+ self.pet._show_activity()
70
+
71
+ def _choose(self) -> str:
72
+ names = [name for name, _weight in self.CHOICES]
73
+ return self.rng.choices(names, weights=[weight for _name, weight in self.CHOICES])[0]
74
+
75
+ def _act(self, action: str) -> None:
76
+ """Play one action in place for its hold time."""
77
+ self.acting = action
78
+ self._hold = self.rng.uniform(*self.HOLD_SECONDS.get(action, (2.0, 4.0)))
79
+ self._last = monotonic()
80
+ self._step.start()
81
+ self.pet._show_activity()
82
+
83
+ def _begin(self) -> None:
84
+ span = self._span()
85
+ if not self._free() or span is None:
86
+ self.start()
87
+ return
88
+ choice = 'walk' if self._walk_next else self._choose()
89
+ self._walk_next = False
90
+ if choice != 'walk':
91
+ self._act(choice)
92
+ return
93
+ left, right = span
94
+ distance = self.rng.randint(*self.DISTANCE)
95
+ x = self.pet.x()
96
+ options = [min(max(x + sign * distance, left), right) for sign in self.rng.sample((-1, 1), 2)]
97
+ target = next((option for option in options if abs(option - x) >= 20), None)
98
+ if target is None:
99
+ self.start()
100
+ return
101
+ self.target_x, self._x, self._last = target, float(x), monotonic()
102
+ self.walking = True
103
+ self._step.start()
104
+ self.pet._show_activity()
105
+
106
+ def tick(self, elapsed: float | None = None) -> None:
107
+ if not self.walking and self.acting is None:
108
+ return
109
+ if not self._free():
110
+ self._finish()
111
+ return
112
+ now = monotonic()
113
+ dt = max(0.0, min(0.05, now - self._last if elapsed is None else elapsed))
114
+ self._last = now
115
+ if self.acting is not None:
116
+ self._hold -= dt
117
+ if self._hold <= 0:
118
+ self._finish()
119
+ return
120
+ remaining = self.target_x - self._x
121
+ step = min(abs(remaining), self.SPEED * dt)
122
+ self._x += step if remaining > 0 else -step
123
+ self.pet.move(round(self._x), self.pet.y())
124
+ if abs(self.target_x - self._x) < 0.5:
125
+ self._finish()
126
+
127
+ def _finish(self) -> None:
128
+ self._step.stop()
129
+ self.walking, self.acting, self.target_x = False, None, None
130
+ self.pet._show_activity()
131
+ if not self.pet._closed and self.pet.isVisible() and not self.pet._settled:
132
+ self.start()
@@ -224,8 +224,11 @@ class WardrobeDraft:
224
224
  self._candidate = copy.deepcopy(self._expected)
225
225
  self.preview = None
226
226
 
227
- def apply(self) -> LayeredRenderer | None:
228
- """Preload, compare and persist. Failure leaves the draft and saved state intact."""
227
+ def apply(self, present: bool = True) -> LayeredRenderer | None:
228
+ """Preload, compare and persist. Failure leaves the draft and saved state intact.
229
+
230
+ ``present`` plays the outfit show on a live pet; summoning skips it so the pet moves at once.
231
+ """
229
232
  candidate = self.appearance
230
233
  self._validate(candidate)
231
234
  prepared = self.catalog.prepare(candidate)
@@ -233,7 +236,7 @@ class WardrobeDraft:
233
236
  if session:
234
237
  if not getattr(session.parent(), 'supports_layered_wardrobe', True):
235
238
  raise ValueError('This active pet does not support layered sprite clothing')
236
- session.apply_appearance(self._expected, candidate, prepared)
239
+ session.apply_appearance(self._expected, candidate, prepared, present=present)
237
240
  else:
238
241
  if self.profiles.get(self.identifier)['appearance'] != self._expected:
239
242
  raise ValueError('Pet appearance changed while previewing')
@@ -63,3 +63,33 @@ class PetBuiltinInstall(QRunnable):
63
63
  except (OSError, ValueError) as failure:
64
64
  error = str(failure)
65
65
  self.signals.finished.emit(error)
66
+
67
+
68
+ class SpriteSignals(QObject):
69
+ finished = Signal(str, str) # preview image path, error
70
+
71
+
72
+ class PetBuiltinSprite(QRunnable):
73
+ """Install a built-in character for sprite pets and render its idle frame as the pet image."""
74
+
75
+ def __init__(self, library, identifier, preview_folder):
76
+ super().__init__()
77
+ self.library, self.identifier, self.preview_folder = library, identifier, preview_folder
78
+ self.cancel = Event()
79
+ self.signals = SpriteSignals()
80
+
81
+ def run(self) -> None:
82
+ from frontengine.show.pet.inkside.library import VERSION, install_builtin
83
+ from frontengine.show.pet.layered_renderer import LayeredRenderer
84
+ try:
85
+ install_builtin(self.library, self.identifier, self.cancel)
86
+ catalog, _errors = self.library.scan()
87
+ character = catalog.resolve({'id': self.identifier, 'version': VERSION}, 'character')
88
+ self.preview_folder.mkdir(parents=True, exist_ok=True)
89
+ preview = self.preview_folder / f'{self.identifier}.png'
90
+ if not LayeredRenderer(character).render('idle', 0).save(str(preview), 'PNG'):
91
+ raise OSError(f'Could not write {preview}')
92
+ except (OSError, ValueError) as failure:
93
+ self.signals.finished.emit('', str(failure))
94
+ return
95
+ self.signals.finished.emit(str(preview), '')
@@ -87,7 +87,7 @@ class PetCustomizationDialog(QDialog):
87
87
  self.controls[key] = control
88
88
  form.addRow(tr(QLabel(), 'pet_' + key + '_label', key.title()), control)
89
89
  for key, values, label, fallback in (
90
- ('behaviour', ('floor', 'wander', 'chase'), 'pet_behaviour_label', 'Behaviour'),
90
+ ('behaviour', ('actions', 'floor', 'wander', 'chase'), 'pet_behaviour_label', 'Behaviour'),
91
91
  ('chatter', CHATTER_LEVELS, 'pet_chatter_label', 'Chatter'),
92
92
  ('motion', MOTION_LEVELS, 'pet_motion_label', 'Animation size')):
93
93
  control = QComboBox()
@@ -9,7 +9,7 @@ from PySide6.QtWidgets import (
9
9
  )
10
10
 
11
11
  from frontengine.show.pet.desktop_pet import (
12
- DesktopPetWidget, BEHAVIOUR_FLOOR, BEHAVIOUR_WANDER, BEHAVIOUR_CHASE, PetTagGame, scan_pet_pack,
12
+ DesktopPetWidget, BEHAVIOUR_ACTIONS, BEHAVIOUR_FLOOR, BEHAVIOUR_WANDER, BEHAVIOUR_CHASE, PetTagGame, scan_pet_pack,
13
13
  )
14
14
  from frontengine.ui.dialog.choose_file_dialog import choose_pet, choose_wav_sound
15
15
  from frontengine.ui.page.utils import (
@@ -96,13 +96,18 @@ class PetSettingUI(SettingPage):
96
96
  self.choose_script_button = tr(QPushButton(), 'pet_choose_script', 'Choose puppet script...')
97
97
  self.choose_script_button.clicked.connect(self.choose_puppet_script)
98
98
  from frontengine.show.pet.inkside.library import builtin_names
99
- self.builtin_puppet = QComboBox()
100
- tr(self.builtin_puppet, 'pet_builtin_puppet_pick', 'Built-in Puppet character', 'setAccessibleName')
99
+ self.builtin_character = QComboBox()
100
+ tr(self.builtin_character, 'pet_builtin_character_pick', 'Built-in character', 'setAccessibleName')
101
101
  for identifier, name in builtin_names():
102
- self.builtin_puppet.addItem(name, identifier)
102
+ self.builtin_character.addItem(name, identifier)
103
+ self.builtin_sprite_button = tr(QPushButton(), 'pet_builtin_character', 'Use built-in character')
104
+ self.builtin_sprite_button.clicked.connect(self.use_builtin_character)
103
105
  self.builtin_puppet_button = tr(QPushButton(), 'pet_builtin_puppet', 'Use built-in Puppet model')
104
106
  self.builtin_puppet_button.clicked.connect(self.use_builtin_puppet)
105
107
  self._puppet_export = None
108
+ self._sprite_install = None
109
+ # (character id, preview image): Start dresses a sprite pet spawned from that image as the character.
110
+ self._builtin_sprite: tuple[str, str] | None = None
106
111
  self.ready_label = tr(QLabel(), "Not Ready")
107
112
 
108
113
  # Size
@@ -120,6 +125,10 @@ class PetSettingUI(SettingPage):
120
125
  # Behaviour
121
126
  self.behaviour_label = tr(QLabel(), "pet_behaviour_label", "Behaviour")
122
127
  self.behaviour_combobox = QComboBox()
128
+ # First item is the default: the floor mode cycling through every action at random.
129
+ self.behaviour_combobox.addItem(
130
+ language_wrapper.language_word_dict.get("pet_behaviour_actions", "Cycle all actions (random)"),
131
+ BEHAVIOUR_ACTIONS)
123
132
  self.behaviour_combobox.addItem(
124
133
  language_wrapper.language_word_dict.get("pet_behaviour_floor", "Walk on floor"), BEHAVIOUR_FLOOR)
125
134
  self.behaviour_combobox.addItem(
@@ -204,9 +213,10 @@ class PetSettingUI(SettingPage):
204
213
  puppet_row = QWidget()
205
214
  puppet_layout = QHBoxLayout(puppet_row)
206
215
  puppet_layout.setContentsMargins(0, 0, 0, 0)
207
- puppet_layout.addWidget(self.builtin_puppet)
216
+ puppet_layout.addWidget(self.builtin_character)
217
+ puppet_layout.addWidget(self.builtin_sprite_button)
208
218
  puppet_layout.addWidget(self.builtin_puppet_button)
209
- source.add_row('pet_builtin_puppet_pick', puppet_row, 'Built-in Puppet character')
219
+ source.add_row('pet_builtin_character_pick', puppet_row, 'Built-in character')
210
220
  self.profile_controls = PetProfileControls(self)
211
221
 
212
222
  appearance = self.add_section("section_appearance", "Appearance")
@@ -339,6 +349,8 @@ class PetSettingUI(SettingPage):
339
349
  profile_id=identifier, profiles=self.profile_controls.profiles,
340
350
  profile_name=self.profile_controls.name.text(),
341
351
  )
352
+ if source_pet is None and self._builtin_sprite is not None and path == self._builtin_sprite[1]:
353
+ self._dress_as_builtin(pet, self._builtin_sprite[0])
342
354
  pet.clone_requested.connect(lambda: self._spawn_pet(pet.profile_session.state(), source_pet=pet))
343
355
  pet.customize_requested.connect(lambda: self.profile_controls.customize(pet.profile_session.identifier))
344
356
  pet.profile_session.changed.connect(self._on_settle_typing_toggled)
@@ -400,7 +412,7 @@ class PetSettingUI(SettingPage):
400
412
  if self._puppet_export is not None:
401
413
  return
402
414
  self.builtin_puppet_button.setEnabled(False)
403
- job = PuppetExport(self.builtin_puppet.currentData(), Path.cwd() / 'pet-assets' / 'puppets')
415
+ job = PuppetExport(self.builtin_character.currentData(), Path.cwd() / 'pet-assets' / 'puppets')
404
416
  self._puppet_export = job
405
417
  job.signals.finished.connect(self._builtin_puppet_ready, Qt.ConnectionType.QueuedConnection)
406
418
  QThreadPool.globalInstance().start(job)
@@ -416,6 +428,42 @@ class PetSettingUI(SettingPage):
416
428
  self.ready_to_play = True
417
429
  self.ready_label.setText(language_wrapper.language_word_dict.get("Ready"))
418
430
 
431
+ def use_builtin_character(self) -> None:
432
+ """Install the chosen INKSIDE character for sprite pets; Start then spawns a pet dressed as it."""
433
+ from frontengine.show.pet.asset_library import PetAssetLibrary
434
+ from frontengine.ui.dialog.pet_asset_install import PetBuiltinSprite
435
+ if self._sprite_install is not None:
436
+ return
437
+ self.builtin_sprite_button.setEnabled(False)
438
+ job = PetBuiltinSprite(PetAssetLibrary(), self.builtin_character.currentData(), Path.cwd() / 'pet-previews')
439
+ self._sprite_install = job
440
+ job.signals.finished.connect(self._builtin_character_ready, Qt.ConnectionType.QueuedConnection)
441
+ QThreadPool.globalInstance().start(job)
442
+
443
+ def _builtin_character_ready(self, preview: str, error: str) -> None:
444
+ identifier, self._sprite_install = self._sprite_install.identifier, None
445
+ self.builtin_sprite_button.setEnabled(True)
446
+ if error:
447
+ self.profile_controls.status.setText(error)
448
+ return
449
+ self.pet_image_path = preview
450
+ self.puppet_script_path = None
451
+ self._builtin_sprite = (identifier, preview)
452
+ self.ready_to_play = True
453
+ self.ready_label.setText(language_wrapper.language_word_dict.get("Ready"))
454
+
455
+ def _dress_as_builtin(self, pet, identifier: str) -> None:
456
+ """Give the pet's identity the built-in character, unless it already wears it."""
457
+ from frontengine.show.pet.inkside.library import VERSION
458
+ from frontengine.show.pet.wardrobe import WardrobeDraft
459
+ reference = {'id': identifier, 'version': VERSION}
460
+ if (pet.profile_session.state().get('appearance') or {}).get('character') == reference:
461
+ return
462
+ catalog, _errors = pet.asset_library.scan()
463
+ draft = WardrobeDraft(self.profile_controls.profiles, pet.profile_session.identifier, catalog)
464
+ draft.choose_character(reference)
465
+ draft.apply(present=False) # no outfit show: a summoned pet sets off at once
466
+
419
467
  def choose_puppet_script(self) -> None:
420
468
  path, _ = QFileDialog.getOpenFileName(self, 'Imervue pet script', '', 'Pet script (*.petscript.json)')
421
469
  if path: