diff --git a/assets/share/dungeon/ui_list/LIST_END_CHECK.png b/assets/share/dungeon/ui_list/LIST_END_CHECK.png new file mode 100644 index 000000000..1e44407b1 Binary files /dev/null and b/assets/share/dungeon/ui_list/LIST_END_CHECK.png differ diff --git a/module/ui/draggable_list.py b/module/ui/draggable_list.py index b35616eae..491285b71 100644 --- a/module/ui/draggable_list.py +++ b/module/ui/draggable_list.py @@ -143,6 +143,13 @@ class DraggableList: if direction == 'right': return 'left' + def wait_bottom_appear(self, main: ModuleBase, skip_first_screenshot=True): + """ + Returns: + bool: If waited + """ + return False + def insight_row(self, row: Keyword, main: ModuleBase, skip_first_screenshot=True) -> bool: """ Args: @@ -180,8 +187,11 @@ class DraggableList: self.drag_page(self.drag_direction, main=main) # Wait for bottoming out - main.wait_until_stable(self.search_button, timer=Timer( - 0, count=0), timeout=Timer(1.5, count=5)) + self.wait_bottom_appear(main, skip_first_screenshot=False) + main.wait_until_stable( + self.search_button, timer=Timer(0, count=0), + timeout=Timer(1.5, count=5) + ) skip_first_screenshot = True if self.cur_buttons and last_buttons == set(self.cur_buttons): if bottom_check.reached(): diff --git a/tasks/dungeon/assets/assets_dungeon_ui_list.py b/tasks/dungeon/assets/assets_dungeon_ui_list.py index 1c0ac3faf..3c5e48ea0 100644 --- a/tasks/dungeon/assets/assets_dungeon_ui_list.py +++ b/tasks/dungeon/assets/assets_dungeon_ui_list.py @@ -23,6 +23,16 @@ LIST_DESCENDING = ButtonWrapper( button=(1125, 643, 1143, 661), ), ) +LIST_END_CHECK = ButtonWrapper( + name='LIST_END_CHECK', + share=Button( + file='./assets/share/dungeon/ui_list/LIST_END_CHECK.png', + area=(465, 587, 556, 622), + search=(445, 567, 576, 642), + color=(218, 210, 215), + button=(465, 587, 556, 622), + ), +) OCR_DUNGEON_LIST = ButtonWrapper( name='OCR_DUNGEON_LIST', share=Button( diff --git a/tasks/dungeon/ui/llist.py b/tasks/dungeon/ui/llist.py index db072b566..c4bdaf921 100644 --- a/tasks/dungeon/ui/llist.py +++ b/tasks/dungeon/ui/llist.py @@ -8,7 +8,7 @@ from module.base.base import ModuleBase from module.base.button import ClickButton from module.base.decorator import run_once from module.base.timer import Timer -from module.base.utils import area_center, area_limit, area_offset, crop, image_size +from module.base.utils import area_center, area_limit, area_offset, color_similarity_2d, crop, image_size from module.logger import logger from module.ocr.ocr import Ocr, OcrResultButton from module.ocr.utils import merge_result_button, split_and_pair_button_attr, split_and_pair_buttons @@ -157,6 +157,13 @@ class DraggableDungeonList(DraggableList): # limit_entrance: True to ensure the teleport button is insight limit_entrance = False + def wait_bottom_appear(self, main: "DungeonUIList", skip_first_screenshot=True): + """ + Returns: + bool: If waited + """ + return main.dungeon_list_wait_list_end(skip_first_screenshot=skip_first_screenshot) + def load_rows(self, main: ModuleBase, allow_early_access=False): """ Args: @@ -251,6 +258,43 @@ class DungeonUIList(UI): LIST_SORTING.set(current, main=self) return True + def dungeon_list_wait_list_end(self, skip_first_screenshot=True): + """ + When swiping down at list end, wait until list rebound + + Returns: + bool: If waited + """ + logger.info('dungeon_list_wait_list_end') + timeout = Timer(1, count=3).start() + empty = False + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if timeout.reached(): + logger.warning('Wait dungeon_list_wait_list_end timeout') + return True + # Check color + image = self.image_crop(LIST_END_CHECK, copy=False) + mask = color_similarity_2d(image, (255, 255, 255)) + cv2.inRange(mask, 0, 235, dst=mask) + mean = cv2.mean(mask)[0] + if mean > 30: + if empty: + # rebound, having rows at bottom now + return True + else: + # Not at bottom from the very beginning + return False + else: + # Blank background + empty = True + continue + def _dungeon_insight_index(self, dungeon: DungeonList): """ Insight a dungeon using pre-defined dungeon indexes from DUNGEON_LIST @@ -350,8 +394,11 @@ class DungeonUIList(UI): # Drag down DUNGEON_LIST.drag_page('down', main=self) - self.wait_until_stable(DUNGEON_LIST.search_button, timer=Timer( - 0, count=0), timeout=Timer(1.5, count=5)) + self.dungeon_list_wait_list_end(skip_first_screenshot=False) + self.wait_until_stable( + DUNGEON_LIST.search_button, timer=Timer(0, count=0), + timeout=Timer(1.5, count=5) + ) self._dungeon_list_reset()