diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 55844c5a..0f31025a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,12 +13,12 @@ name: "CodeQL" on: push: - branches: [ main, master, develop, dev, 2.0.0] + branches: [main, master, develop, dev, 2.0.0] pull_request: # The branches below must be a subset of the branches above - branches: [ develop, dev, 2.0.0 ] + branches: [develop, dev, 2.0.0] schedule: - - cron: '26 13 * * 6' + - cron: "26 13 * * 6" jobs: analyze: @@ -28,40 +28,40 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'python' ] + language: ["python"] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more: # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed steps: - - name: Checkout repository - uses: actions/checkout@v2 + - name: Checkout repository + uses: actions/checkout@v2 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language - #- run: | - # make bootstrap - # make release + #- run: | + # make bootstrap + # make release - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/PyInstaller/hooks/hook-cv2.py b/PyInstaller/hooks/hook-cv2.py deleted file mode 100644 index 620319d3..00000000 --- a/PyInstaller/hooks/hook-cv2.py +++ /dev/null @@ -1,24 +0,0 @@ -""" -Copyright (c) 2020 PyInstaller Development Team. - -This file is distributed under the terms of the GNU General Public -License (version 2.0 or later). - -The full license is available in LICENSE.GPL.txt, distributed with -this software. - -SPDX-License-Identifier: GPL-2.0-or-later - -https://github.com/pyinstaller/pyinstaller-hooks-contrib/blob/master/src/_pyinstaller_hooks_contrib/hooks/stdhooks/hook-cv2.py -""" - -from PyInstaller.utils.hooks import collect_data_files, collect_dynamic_libs - -hiddenimports = ["numpy"] - -# Include any DLLs from site-packages/cv2 (opencv_videoio_ffmpeg*.dll can be found there in the PyPI version) -binaries = collect_dynamic_libs("cv2") - -# https://github.com/pyinstaller/pyinstaller-hooks-contrib/issues/110 -# OpenCV loader from 4.5.4.60 requires extra config files and modules -datas = collect_data_files("cv2", include_py_files=True, includes=["**/*.py"]) diff --git a/README.md b/README.md index c53827e9..1533db35 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ This program can be used to automatically start, split, and reset your preferred ### Compatibility +- Python 3.9+ - Windows 10 and 11. ### Building @@ -30,7 +31,7 @@ This program can be used to automatically start, split, and reset your preferred - Python 3.9 - 3.10. - Microsoft Visual C++ 14.0 or greater may be required to build the executable. Get it with [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/). -- Node is optional, but required for complete linting (using Pyright). + - Read [requirements.txt](/scripts/requirements.txt) for more information on how to install, run and build the python code. - Run `./scripts/install.ps1` to install all dependencies. - Run the app directly with `./scripts/start.ps1 [--auto-controlled]`. @@ -97,6 +98,10 @@ This program can be used to automatically start, split, and reset your preferred There are currently performance issues, but it might be more convenient. If you want to use this with OBS' Virtual Camera, use the [Virtualcam plugin](https://obsproject.com/forum/resources/obs-virtualcam.949/) instead. +#### Capture Device + +Select the Video Capture Device that you wanna use if selecting the `Video Capture Device` Capture Method. Will show `[occupied]` if a device is detected but can't be started. + #### Show Live Similarity - Displays the live similarity between the capture region and the current split image. This number is between 0 and 1, with 1 being a perfect match. @@ -240,7 +245,7 @@ Still need help? - Created by [Toufool](https://twitter.com/Toufool) and [Faschz](https://twitter.com/faschz). - [Harutaka Kawamura](https://github.com/harupy/) for the snipping tool code that I used to integrate into the autosplitter. - [amaringos](https://twitter.com/amaringos) for the icon. -- [ZanasoBayncuh](https://twitter.com/ZanasoBayncuh) for motivating me to start this project back up and for all of the time spent testing and suggesting improvements. +- [Zana_G](https://www.twitch.tv/zana_g) for motivating me to start this project back up and for all of the time spent testing and suggesting improvements. - [Avasam](https://twitter.com/Avasam06) for their continued work on making an incredible amount of improvements and changes to AutoSplit while I have not had the time/motivation to do so. - [KaDiWa](https://github.com/KaDiWa4) for the LiveSplit integration. - [Tyron18](https://twitter.com/Tyron18_) for assisting with Windows 11 testing. diff --git a/res/about.ui b/res/about.ui index 05e4914a..04ff482c 100644 --- a/res/about.ui +++ b/res/about.ui @@ -52,7 +52,7 @@ 10 44 - 171 + 241 32 @@ -65,7 +65,7 @@ 10 21 - 161 + 241 16 @@ -76,15 +76,16 @@ - 30 - 95 - 204 - 32 + 10 + 90 + 241 + 41 - If you enjoy using this program, please -consider donating. Thank you! + If you enjoy using this program, +please consider donating. +Thank you! Qt::AlignCenter @@ -128,6 +129,9 @@ consider donating. Thank you! true + ok_button + donate_text_label + donate_button_label icon_label version_label created_by_label diff --git a/res/settings.ui b/res/settings.ui index 239356da..4f5cc6eb 100644 --- a/res/settings.ui +++ b/res/settings.ui @@ -6,8 +6,8 @@ 0 0 - 289 - 621 + 291 + 661 @@ -18,14 +18,14 @@ - 289 - 621 + 291 + 661 - 289 - 621 + 291 + 661 @@ -50,7 +50,7 @@ 10 - 180 + 200 271 181 @@ -175,9 +175,9 @@ 10 - 370 + 390 271 - 241 + 261 @@ -196,7 +196,7 @@ 167 - 26 + 25 88 22 @@ -238,7 +238,7 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i 6 - 29 + 28 161 16 @@ -251,7 +251,7 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i 6 - 117 + 118 161 16 @@ -264,7 +264,7 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i 167 - 114 + 115 87 22 @@ -305,7 +305,7 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i 167 - 56 + 55 52 22 @@ -333,7 +333,7 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i 6 - 144 + 143 235 20 @@ -352,7 +352,7 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i 6 - 173 + 193 261 61 @@ -364,7 +364,7 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i - <html><head/><body><p>Custom image settings and flags are set in the <br></br> image file name. These will override the default <br></br> values. View the <a href="https://github.com/Toufool/Auto-Split#readme"><span style=" text-decoration: underline; color:#0000ff;">README</span></a> for full details on all <br></br> available custom image settings.</p></body></html> + <html><head/><body><p>Custom image settings and flags are set in the <br></br> image file name. These will override the default <br></br> values. View the <a href="https://github.com/{GITHUB_REPOSITORY}#readme"><span style=" text-decoration: underline; color:#0000ff;">README</span></a> for full details on all <br></br> available custom image settings.</p></body></html> @@ -399,6 +399,22 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i 999999999 + + + + 6 + 168 + 151 + 20 + + + + Enable auto reset image + + + true + + @@ -406,7 +422,7 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i 10 10 271 - 161 + 191 @@ -550,7 +566,7 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i 180 - 28 + 30 81 21 @@ -649,6 +665,52 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i true + + + + 180 + 155 + 81 + 21 + + + + Qt::NoFocus + + + Set Hotkey + + + + + + 6 + 154 + 71 + 31 + + + + Toggle auto +reset image + + + + + + 76 + 155 + 94 + 20 + + + + + + + true + + @@ -666,8 +728,6 @@ It is highly recommended to NOT use pHash if you use masked images. It is very i default_delay_time_spinbox default_pause_time_spinbox loop_splits_checkbox - fps_limit_spinbox - live_capture_region_checkbox diff --git a/src/AutoSplit.py b/src/AutoSplit.py index 949e7e8d..0a98c6f8 100644 --- a/src/AutoSplit.py +++ b/src/AutoSplit.py @@ -773,25 +773,28 @@ def __reset_if_should(self, capture: cv2.Mat | None): Checks if we should reset, resets if it's the case, and returns the result """ if self.reset_image: - similarity = self.reset_image.compare_with_capture(self, capture) - threshold = self.reset_image.get_similarity_threshold(self) - - paused = time() - self.run_start_time <= self.reset_image.get_pause_time(self) - if paused: - should_reset = False - self.table_reset_image_live_label.setText("paused") - else: - should_reset = similarity >= threshold - if similarity > self.reset_highest_similarity: - self.reset_highest_similarity = similarity - self.table_reset_image_highest_label.setText(decimal(self.reset_highest_similarity)) - self.table_reset_image_live_label.setText(decimal(similarity)) + if self.settings_dict["enable_auto_reset"]: + similarity = self.reset_image.compare_with_capture(self, capture) + threshold = self.reset_image.get_similarity_threshold(self) + + paused = time() - self.run_start_time <= self.reset_image.get_pause_time(self) + if paused: + should_reset = False + self.table_reset_image_live_label.setText("paused") + else: + should_reset = similarity >= threshold + if similarity > self.reset_highest_similarity: + self.reset_highest_similarity = similarity + self.table_reset_image_highest_label.setText(decimal(self.reset_highest_similarity)) + self.table_reset_image_live_label.setText(decimal(similarity)) - self.table_reset_image_threshold_label.setText(decimal(threshold)) + self.table_reset_image_threshold_label.setText(decimal(threshold)) - if should_reset: - send_command(self, "reset") - self.reset() + if should_reset: + send_command(self, "reset") + self.reset() + else: + self.table_reset_image_live_label.setText("disabled") return self.__check_for_reset_state_update_ui() diff --git a/src/hotkeys.py b/src/hotkeys.py index d5fa6f90..a7aff538 100644 --- a/src/hotkeys.py +++ b/src/hotkeys.py @@ -20,8 +20,8 @@ PRESS_A_KEY_TEXT = "Press a key..." Commands = Literal["split", "start", "pause", "reset", "skip", "undo"] -Hotkeys = Literal["split", "reset", "skip_split", "undo_split", "pause"] -HOTKEYS: list[Hotkeys] = ["split", "reset", "skip_split", "undo_split", "pause"] +Hotkey = Literal["split", "reset", "skip_split", "undo_split", "pause", "toggle_auto_reset_image"] +HOTKEYS: list[Hotkey] = ["split", "reset", "skip_split", "undo_split", "pause", "toggle_auto_reset_image"] def before_setting_hotkey(autosplit: AutoSplit): @@ -195,13 +195,20 @@ def __remove_key_already_set(autosplit: AutoSplit, key_name: str): getattr(autosplit.SettingsWidget, f"{hotkey}_input").setText("") -def __get_hotkey_action(autosplit: AutoSplit, hotkey: Hotkeys): +def __get_hotkey_action(autosplit: AutoSplit, hotkey: Hotkey): if hotkey == "split": return autosplit.start_auto_splitter if hotkey == "skip_split": return lambda: autosplit.skip_split(True) if hotkey == "undo_split": return lambda: autosplit.undo_split(True) + if hotkey == "toggle_auto_reset_image": + def toggle_auto_reset_image(): + new_value = not autosplit.settings_dict["enable_auto_reset"] + autosplit.settings_dict["enable_auto_reset"] = new_value + if autosplit.SettingsWidget: + autosplit.SettingsWidget.enable_auto_reset_image_checkbox.setChecked(new_value) + return toggle_auto_reset_image return getattr(autosplit, f"{hotkey}_signal").emit @@ -215,7 +222,7 @@ def is_valid_hotkey_name(hotkey_name: str): # reduce duplicated code. We should use a dictionary of hotkey class or something. -def set_hotkey(autosplit: AutoSplit, hotkey: Hotkeys, preselected_hotkey_name: str = ""): +def set_hotkey(autosplit: AutoSplit, hotkey: Hotkey, preselected_hotkey_name: str = ""): if autosplit.SettingsWidget: # Unfocus all fields cast(QtWidgets.QDialog, autosplit.SettingsWidget).setFocus() diff --git a/src/menu_bar.py b/src/menu_bar.py index 98458605..37dd5602 100644 --- a/src/menu_bar.py +++ b/src/menu_bar.py @@ -14,7 +14,7 @@ from capture_method import (CAPTURE_METHODS, CameraInfo, CaptureMethodEnum, change_capture_method, get_all_video_capture_devices) from gen import about, design, resources_rc, settings as settings_ui, update_checker # noqa F401 -from hotkeys import HOTKEYS, Hotkeys, set_hotkey +from hotkeys import HOTKEYS, Hotkey, set_hotkey from utils import (AUTOSPLIT_VERSION, FIRST_WIN_11_BUILD, GITHUB_REPOSITORY, WINDOWS_BUILD_NUMBER, decimal, fire_and_forget) @@ -223,8 +223,8 @@ def __init__(self, autosplit: AutoSplit): for method in capture_method_values])) # endregion - # Hotkeys initial values and bindings - def hotkey_connect(hotkey: Hotkeys): + # Hotkey initial values and bindings + def hotkey_connect(hotkey: Hotkey): return lambda: set_hotkey(self.autosplit, hotkey) for hotkey in HOTKEYS: hotkey_input: QtWidgets.QLineEdit = getattr(self, f"{hotkey}_input") @@ -253,6 +253,7 @@ def hotkey_connect(hotkey: Hotkeys): self.default_delay_time_spinbox.setValue(autosplit.settings_dict["default_delay_time"]) self.default_pause_time_spinbox.setValue(autosplit.settings_dict["default_pause_time"]) self.loop_splits_checkbox.setChecked(autosplit.settings_dict["loop_splits"]) + self.enable_auto_reset_image_checkbox.setChecked(autosplit.settings_dict["enable_auto_reset"]) # endregion # region Binding # Capture Settings @@ -282,6 +283,9 @@ def hotkey_connect(hotkey: Hotkeys): self.loop_splits_checkbox.stateChanged.connect(lambda: self.__set_value( "loop_splits", self.loop_splits_checkbox.isChecked())) + self.enable_auto_reset_image_checkbox.stateChanged.connect(lambda: self.__set_value( + "enable_auto_reset", + self.enable_auto_reset_image_checkbox.isChecked())) # endregion self.show() @@ -302,8 +306,10 @@ def get_default_settings_from_ui(autosplit: AutoSplit): "undo_split_hotkey": default_settings_dialog.undo_split_input.text(), "skip_split_hotkey": default_settings_dialog.skip_split_input.text(), "pause_hotkey": default_settings_dialog.pause_input.text(), + "toggle_auto_reset_image_hotkey": default_settings_dialog.toggle_auto_reset_image_input.text(), "fps_limit": default_settings_dialog.fps_limit_spinbox.value(), "live_capture_region": default_settings_dialog.live_capture_region_checkbox.isChecked(), + "enable_auto_reset": default_settings_dialog.enable_auto_reset_image_checkbox.isChecked(), "capture_method": CAPTURE_METHODS.get_method_by_index( default_settings_dialog.capture_method_combobox.currentIndex()), "capture_device_id": default_settings_dialog.capture_device_combobox.currentIndex(), diff --git a/src/user_profile.py b/src/user_profile.py index a0990f4f..d7d3e0c8 100644 --- a/src/user_profile.py +++ b/src/user_profile.py @@ -23,8 +23,10 @@ class UserProfileDict(TypedDict): undo_split_hotkey: str skip_split_hotkey: str pause_hotkey: str + toggle_auto_reset_image_hotkey: str fps_limit: int live_capture_region: bool + enable_auto_reset: bool capture_method: str | CaptureMethodEnum capture_device_id: int capture_device_name: str @@ -33,7 +35,6 @@ class UserProfileDict(TypedDict): default_delay_time: int default_pause_time: float loop_splits: bool - split_image_directory: str captured_window_title: str capture_region: Region @@ -45,8 +46,10 @@ class UserProfileDict(TypedDict): undo_split_hotkey="", skip_split_hotkey="", pause_hotkey="", + toggle_auto_reset_image_hotkey="", fps_limit=60, live_capture_region=True, + enable_auto_reset=True, capture_method=CAPTURE_METHODS.get_method_by_index(0), capture_device_id=0, capture_device_name="",