def swapSlides(self): self.remaining = 0 self.slide_index += 1 self.slide_index %= self.SLIDE_NUMS self.slide_surface_prev = pygame.image.load( find_abs(f"bg_slide{(self.slide_index - 1) % self.SLIDE_NUMS}.png", asset_locations())) self.slide_surface_next = pygame.image.load( find_abs(f"bg_slide{self.slide_index}.png", asset_locations()))
def setCheckboxBg(self, value, obj): img = pygame.image.load( find_abs("ui/box_check.png" if value else "ui/box_clear.png", allowed_areas=asset_locations())) if img.get_size() != obj.rect.size: img = pygame.transform.smoothscale( img, (obj.rect.width, obj.rect.height)) obj.set_image(img)
def updateFlipCheckbox(self): img = pygame.image.load( find_abs( "ui/box_check.png" if self.getSelectedAttribute("flip", False) else "ui/box_clear.png", allowed_areas=asset_locations(), )) if img.get_size() != self.flip_image.rect.size: img = pygame.transform.smoothscale( img, (self.flip_image.rect.width, self.flip_image.rect.height)) self.flip_image.set_image(img)
def action(): import yaml """Go through and try fixing the bots.""" for bot in old_bots: dirpath = os.path.join(path, bot[:-4]) # Folder if os.path.isdir(dirpath): import shutil shutil.rmtree(dirpath) os.mkdir(dirpath) # config.bot with open(os.path.join(path, bot), "r") as f: config = yaml.safe_load(f) bot_script = config.get("script", "code.py") preview_image = config.get("preview_path", "preview.png") for keyword in ["script", "preview_path"]: if keyword in config: del config[keyword] with open(os.path.join(dirpath, "config.bot"), "w") as f: f.write(yaml.dump(config)) # code.py try: code_path = os.path.join( find_abs_directory("workspace/code/"), bot_script) with open(code_path, "r") as f: code = f.read() except: code = "" with open(os.path.join(dirpath, "code.py"), "w") as f: f.write(code) # preview.png try: preview = find_abs(preview_image, asset_locations()) with open(preview, "rb") as f: preview_data = f.read() except: preview_data = bytes() with open(os.path.join(dirpath, "preview.png"), "wb") as f: f.write(preview_data) # Remove the old bot os.remove(os.path.join(path, bot)) # Additionally, we need to update all sim files to no longer use the .bot prefix actual_dir = find_abs_directory("workspace/sims/") for file in os.listdir(actual_dir): if os.path.isfile(os.path.join( actual_dir, file)) and file.endswith(".sim"): with open(os.path.join(actual_dir, file), "r") as f: config = yaml.safe_load(f) for x in range(len(config.get("bots", []))): if config["bots"][x].endswith(".bot"): config["bots"][x] = config["bots"][x][:-4] with open(os.path.join(actual_dir, file), "w") as f: f.write(yaml.dump(config))
def image_path(self, value): from ev3sim.file_helper import find_abs image_path = find_abs(value, allowed_areas=asset_locations()) if image_path != self._image_path: self._image_path = image_path self.image = pygame.image.load(self._image_path) try: self.calculatePoints() except: pass
def generateVisual(self, size, container, manager, idx): self.container = container off = self.offset(size) label_size = ((size[0] - 40) / 2 - 10, 40) label_pos = (off[0] + 20, off[1]) label = pygame_gui.elements.UILabel( relative_rect=pygame.Rect(*label_pos, *label_size), manager=manager, object_id=pygame_gui.core.ObjectID(f"{idx}-file-label", "entry-label"), container=container, text=self.title, ) button_size = ((size[0] - 40) * 0.25 - 20, 44) button_size = [min(button_size[0], button_size[1])] * 2 file_size = ((size[0] - 40) / 2 - button_size[0] - 30, 40) button_pos = ( off[0] + 50 + label_size[0] + file_size[0], off[1] - 2, ) file_pos = (off[0] + 40 + label_size[0], off[1]) click = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*button_pos, *button_size), manager=manager, object_id=pygame_gui.core.ObjectID(f"{idx+2}-button", "file-button"), container=container, text="", ) img = pygame.image.load( find_abs("ui/folder.png", allowed_areas=asset_locations())) if img.get_size() != button_size: img = pygame.transform.smoothscale(img, button_size) click_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect(*button_pos, *button_size), manager=manager, object_id=pygame_gui.core.ObjectID(f"{idx+3}-image", "file-image"), container=container, image_surface=img, ) self.filename = pygame_gui.elements.UILabel( relative_rect=pygame.Rect(*file_pos, *file_size), manager=manager, object_id=pygame_gui.core.ObjectID(f"{idx+1}-file-name", "entry-label"), container=container, text=self.current if self.current else "", ) return [label, self.filename, click, click_icon]
def initFromKwargs(self, **kwargs): super().initFromKwargs(**kwargs) from ev3sim.file_helper import find_abs self.font_style = kwargs.get("font_style", "fonts/OpenSans-SemiBold.ttf") self.font_path = find_abs(self.font_style, allowed_areas=asset_locations()) self.font_size = kwargs.get("font_size", 30) self.hAlignment = kwargs.get("hAlignment", "l") self.vAlignment = kwargs.get("vAlignment", "t") self.text = kwargs.get("text", "Test")
def updateSpawnCheckbox(self): tile_pos = self.getSelectedAttribute("position") spawn = self.previous_info["settings"]["rescue"]["BOT_SPAWN_POSITION"][ 0][0] img = pygame.image.load( find_abs( "ui/box_check.png" if tile_pos[0] == spawn[0] and tile_pos[1] == spawn[1] else "ui/box_clear.png", allowed_areas=asset_locations(), )) if img.get_size() != self.spawn_image.rect.size: img = pygame.transform.smoothscale( img, (self.spawn_image.rect.width, self.spawn_image.rect.height)) self.spawn_image.set_image(img)
def generateObjects(self): # First, find all batch files. if not self.in_error: self.available_batches = [] error_batches = [] for rel_dir in batch_locations(): # Only show custom sims. if not rel_dir.startswith("workspace/custom/"): continue try: actual_dir = find_abs_directory(rel_dir) except: continue for batch in BatchValidator.all_valid_in_dir(actual_dir): # Show the dir name. try: with open(os.path.join(actual_dir, batch), "r") as f: config = yaml.safe_load(f) if not config.get("hidden", False): rest = rel_dir directory = "" while not directory: rest, directory = os.path.split(rest) self.available_batches.append( (directory, os.path.join(actual_dir, batch), actual_dir, batch)) except Exception as e: sentry_sdk.capture_exception(e) error_batches.append(os.path.join(actual_dir, batch)) if self.first_launch and error_batches: self.first_launch = False self.in_error = True self.addErrorDialog( 'A problem occured loading the following batches:<br><br><font color="#cc0000">' + "<br>".join(batch for batch in error_batches) + "</font>") return for i, batch in enumerate(self.available_batches): if i == self.batch_index: try: with open(batch[1], "r") as f: config = yaml.safe_load(f) # Update batch information preset_path = find_abs(config["preset_file"], allowed_areas=["workspace"]) with open(preset_path, "r") as f: preset_config = yaml.safe_load(f) preset_preview = find_abs(preset_config["preview_path"], allowed_areas=["workspace"]) self.preview_image_source = pygame.image.load( preset_preview) except Exception as e: sentry_sdk.capture_exception(e) self.setBatchIndex(-1) self.addErrorDialog( '<font color="#cc0000">The task you have selected has some internal errors EV3Sim cannot resolve.</font><br><br>' + "This can be caused by moving/renaming a bot as well as a few other things.<br><br>" + "If you'd like to fix this, then try manually editing the sim file in a text editor or contact the developers." ) return # Draw Background self.bg = pygame_gui.elements.UIPanel( relative_rect=pygame.Rect(0, 0, *self._size), starting_layer_height=-1, manager=self, object_id=pygame_gui.core.ObjectID("background"), ) self._all_objs.append(self.bg) # Scrolling container old_y = getattr(getattr(self, "scrolling_container", None), "cur_y", 0) self.scrolling_container = CustomScroll( relative_rect=pygame.Rect(0, 0, self._size[0], 5 * self._size[1]), manager=self, object_id=pygame_gui.core.ObjectID("scroll_container"), ) picture_width = 360 self.scrolling_container.elems_size = picture_width * 0.4 self.scrolling_container.span_elems = 4 self.scrolling_container.num_elems = len(self.available_batches) scrolling_size = (self._size[0] / 4 + self._size[0] / 5, self._size[1] * 0.95 - min(self._size[1] / 6, 90) + 20) # Setting dimensions and positions on a UIScrollingContainer seems buggy. This works. self.scrolling_container.set_dimensions(scrolling_size) self.scrolling_container.set_position(scrolling_size) self.scrolling_container.cur_y = old_y self.scrolling_container.set_scroll(old_y) self._all_objs.append(self.scrolling_container) # The batch buttons button_size = self._size[0] / 4, 60 info_size = self._size[0] / 4 - 20, 15 batch_rect = lambda i: (self._size[0] / 10, self._size[1] / 10 + i * button_size[1] * 1.5) info_rect = lambda b_r: ( b_r[0] + button_size[0] - info_size[0] - 10, b_r[1] + button_size[1] - info_size[1] - 5, ) self.batch_buttons = [] for i, (show, batch, actual_dir, filename) in enumerate(self.available_batches): self.batch_buttons.append( pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*batch_rect(i), *button_size), text=show, manager=self, container=self.scrolling_container, object_id=pygame_gui.core.ObjectID(show + "-" + str(i), "list_button"), )) self.addButtonEvent(show + "-" + str(i), self.setBatchIndex, i) self._all_objs.extend(self.batch_buttons) # Remove remove_size = self._size[0] / 8, min(self._size[1] / 6, 90) remove_icon_size = remove_size[1] * 0.6, remove_size[1] * 0.6 remove_batch_pos = (self._size[0] / 3 - 2 * remove_size[0] - 15, self._size[1] * 0.95 - remove_size[1]) self.remove_batch = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*remove_batch_pos, *remove_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("remove_batch", "cancel-changes"), ) self.addButtonEvent("remove_batch", self.clickRemove) if not self.remove_enable: self.remove_batch.disable() remove_batch_path = find_abs("ui/bin.png", allowed_areas=asset_locations()) self.remove_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(remove_batch_pos, remove_size, remove_icon_size), *remove_icon_size), image_surface=pygame.image.load(remove_batch_path), manager=self, object_id=pygame_gui.core.ObjectID("remove_batch-icon"), ) self._all_objs.append(self.remove_batch) self._all_objs.append(self.remove_icon) preview_size = self._size[0] / 4, self._size[1] / 4 preview_size = ( min(preview_size[0], (preview_size[1] * 4) // 3), min(preview_size[1], (preview_size[0] * 3) // 4), ) preview_image_pos = (self._size[0] * 0.9 - preview_size[0], self._size[1] * 0.1) self.preview_image = pygame_gui.elements.UIImage( relative_rect=pygame.Rect(*preview_image_pos, *preview_size), image_surface=pygame.Surface(self._size), manager=self, object_id=pygame_gui.core.ObjectID("preview-image"), ) self._all_objs.append(self.preview_image) code_size = preview_size[0] * 0.4, preview_size[1] * 0.4 code_button_pos = ( self._size[0] * 0.9 - code_size[0] - 10, self._size[1] * 0.1 + preview_size[1] + 10, ) code_icon_size = code_size[1] * 0.6, code_size[1] * 0.6 self.code_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*code_button_pos, *code_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("bot-code", "settings_buttons"), ) self.addButtonEvent("bot-code", self.clickCode) if not self.code_enable: self.code_button.disable() code_icon_path = find_abs("ui/code.png", allowed_areas=asset_locations()) self.code_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(code_button_pos, code_size, code_icon_size), *code_icon_size), image_surface=pygame.image.load(code_icon_path), manager=self, object_id=pygame_gui.core.ObjectID("code-icon"), ) self._all_objs.append(self.code_button) self._all_objs.append(self.code_icon) bots_button_pos = ( self._size[0] * 0.9 - preview_size[0] + 10, self._size[1] * 0.1 + preview_size[1] + 10, ) self.bots_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*bots_button_pos, *code_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("bot-bots", "settings_buttons"), ) self.addButtonEvent("bot-bots", self.clickBots) if not self.bots_enable: self.bots_button.disable() bots_icon_path = find_abs("ui/bot.png", allowed_areas=asset_locations()) self.bots_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(bots_button_pos, code_size, code_icon_size), *code_icon_size), image_surface=pygame.image.load(bots_icon_path), manager=self, object_id=pygame_gui.core.ObjectID("bots-icon"), ) self._all_objs.append(self.bots_button) self._all_objs.append(self.bots_icon) start_size = self._size[0] / 4, min(self._size[1] / 4, 120) start_icon_size = start_size[1] * 0.6, start_size[1] * 0.6 start_button_pos = (self._size[0] * 0.9 - start_size[0], self._size[1] * 0.9 - start_size[1]) self.start_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*start_button_pos, *start_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("start-sim", "action_button"), ) self.addButtonEvent("start-sim", self.clickStart) if not self.start_enable: self.start_button.disable() start_icon_path = find_abs("ui/start_sim.png", allowed_areas=asset_locations()) self.start_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(start_button_pos, start_size, start_icon_size), *start_icon_size), image_surface=pygame.image.load(start_icon_path), manager=self, object_id=pygame_gui.core.ObjectID("start-sim-icon"), ) self._all_objs.append(self.start_button) self._all_objs.append(self.start_icon) self.changeSelectedTheming() super().generateObjects()
def generateObjects(self): from ev3sim.visual.manager import ScreenObjectManager self.show_custom = False # First, check if there are any valid batches in the custom folder. for rel_dir in batch_locations(): # Only consider custom sims. if not rel_dir.startswith("workspace/custom/"): continue try: actual_dir = find_abs_directory(rel_dir) except: continue for _ in BatchValidator.all_valid_in_dir(actual_dir): self.show_custom = True break # In order to respect theme changes, objects must be built in initWithKwargs self.bg = pygame_gui.elements.UIPanel( relative_rect=pygame.Rect(0, 0, *self._size), starting_layer_height=-1, manager=self, object_id=pygame_gui.core.ObjectID("background"), ) self._all_objs.append(self.bg) self.title = pygame_gui.elements.UITextBox( relative_rect=pygame.Rect(0, 0, -1, -1), html_text="EV3<i>Sim</i>", manager=self, object_id=pygame_gui.core.ObjectID("title"), ) self.title.set_position( ((self._size[0] - self.title.rect.width) / 2, 50)) self._all_objs.append(self.title) self.button_size = ((self._size[0] / 4, self._size[1] / 10) if self.show_custom else (self._size[0] / 4, self._size[1] / 8)) settings_size = self.button_size[0] * 0.3, self.button_size[1] bot_size = settings_size settings_icon_size = settings_size[1] * 0.6, settings_size[1] * 0.6 bot_icon_size = bot_size[1] * 0.6, bot_size[1] * 0.6 settings_icon_path = find_abs("ui/settings.png", allowed_areas=asset_locations()) bot_icon_path = find_abs("ui/bot.png", allowed_areas=asset_locations()) self.soccer_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*self.buttonPos(0), *self.button_size), text="Soccer", manager=self, object_id=pygame_gui.core.ObjectID("soccer_button", "menu_button"), ) self.addButtonEvent("soccer_button", lambda: self.playSim("soccer.yaml")) self._all_objs.append(self.soccer_button) soccer_settings_button_pos = [ self.buttonPos(0)[0] + self.button_size[0] + 20, self.buttonPos(0)[1] ] self.soccer_settings_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*soccer_settings_button_pos, *settings_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("soccer-settings", "settings_buttons"), ) self.addButtonEvent("soccer-settings", self.clickSimSettings, "soccer.yaml") self.soccer_settings_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(soccer_settings_button_pos, settings_size, settings_icon_size), *settings_icon_size), image_surface=pygame.image.load(settings_icon_path), manager=self, object_id=pygame_gui.core.ObjectID("soccer-settings-icon"), ) self._all_objs.append(self.soccer_settings_button) self._all_objs.append(self.soccer_settings_icon) soccer_bot_button_pos = [ self.buttonPos(0)[0] + self.button_size[0] + settings_size[0] + 40, self.buttonPos(0)[1], ] self.soccer_bot_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*soccer_bot_button_pos, *bot_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("soccer-bot", "settings_buttons"), ) self.addButtonEvent("soccer-bot", self.clickSimBots, "soccer.yaml") self.soccer_bot_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(soccer_bot_button_pos, bot_size, bot_icon_size), *bot_icon_size), image_surface=pygame.image.load(bot_icon_path), manager=self, object_id=pygame_gui.core.ObjectID("soccer-bot-icon"), ) self._all_objs.append(self.soccer_bot_button) self._all_objs.append(self.soccer_bot_icon) self.rescue_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*self.buttonPos(1), *self.button_size), text="Rescue", manager=self, object_id=pygame_gui.core.ObjectID("rescue_button", "menu_button"), ) self.addButtonEvent("rescue_button", lambda: self.playSim("rescue.yaml")) self._all_objs.append(self.rescue_button) rescue_settings_button_pos = [ self.buttonPos(1)[0] + self.button_size[0] + 20, self.buttonPos(1)[1] ] self.rescue_settings_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*rescue_settings_button_pos, *settings_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("rescue-settings", "settings_buttons"), ) self.addButtonEvent("rescue-settings", self.clickSimSettings, "rescue.yaml") self.rescue_settings_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(rescue_settings_button_pos, settings_size, settings_icon_size), *settings_icon_size), image_surface=pygame.image.load(settings_icon_path), manager=self, object_id=pygame_gui.core.ObjectID("rescue-settings-icon"), ) self._all_objs.append(self.rescue_settings_button) self._all_objs.append(self.rescue_settings_icon) rescue_bot_button_pos = [ self.buttonPos(1)[0] + self.button_size[0] + settings_size[0] + 40, self.buttonPos(1)[1], ] self.rescue_bot_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*rescue_bot_button_pos, *bot_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("rescue-bot", "settings_buttons"), ) self.addButtonEvent("rescue-bot", self.clickSimBots, "rescue.yaml") self.rescue_bot_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(rescue_bot_button_pos, bot_size, bot_icon_size), *bot_icon_size), image_surface=pygame.image.load(bot_icon_path), manager=self, object_id=pygame_gui.core.ObjectID("rescue-bot-icon"), ) self._all_objs.append(self.rescue_bot_button) self._all_objs.append(self.rescue_bot_icon) if self.show_custom: self.custom_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*self.buttonPos(2), *self.button_size), text="Custom", manager=self, object_id=pygame_gui.core.ObjectID("custom_button", "menu_button"), ) self.addButtonEvent("custom_button", self.clickCustom) self._all_objs.append(self.custom_button) self.bot_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect( *self.buttonPos(3 if self.show_custom else 2), *self.button_size), text="Bots", manager=self, object_id=pygame_gui.core.ObjectID("bots_button", "menu_button"), ) self.addButtonEvent( "bots_button", lambda: ScreenObjectManager.instance.pushScreen(ScreenObjectManager .SCREEN_BOTS), ) self._all_objs.append(self.bot_button) self.settings_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect( *self.buttonPos(4 if self.show_custom else 3), *self.button_size), text="Settings", manager=self, object_id=pygame_gui.core.ObjectID("main_settings_button", "menu_button"), ) def clickSettings(): ScreenObjectManager.instance.pushScreen( ScreenObjectManager.SCREEN_SETTINGS, file=find_abs("user_config.yaml", config_locations()), settings=main_settings, ) ScreenObjectManager.instance.screens[ ScreenObjectManager.SCREEN_SETTINGS].clearEvents() self.addButtonEvent("main_settings_button", clickSettings) self._all_objs.append(self.settings_button) super().generateObjects()
def generateObjects(self): # First, find all bot files. if not self.in_error: self.available_bots = [] error_bots = [] for rel_dir in bot_locations(): try: actual_dir = find_abs_directory(rel_dir) except: continue for bot in BotValidator.all_valid_in_dir(actual_dir): try: # Show everything except dir and .bot with open(os.path.join(actual_dir, bot, "config.bot"), "r") as f: config = yaml.safe_load(f) # If we are hidden, or in edit mode with hidden_edit, then don't show. if not config.get("hidden", False) and not ( config.get("hidden_edit", False) and len(self.bot_keys) == 0): self.available_bots.append( (bot, os.path.join(actual_dir, bot), rel_dir, bot)) except Exception as e: sentry_sdk.capture_exception(e) error_bots.append(os.path.join(actual_dir, bot)) if self.first_launch and error_bots: self.first_launch = False self.in_error = True self.addErrorDialog( 'A problem occured loading the following bots:<br><br><font color="#cc0000">' + "<br>".join(bot for bot in error_bots) + "</font>") return self.bg = pygame_gui.elements.UIPanel( relative_rect=pygame.Rect(0, 0, *self._size), starting_layer_height=-1, manager=self, object_id=pygame_gui.core.ObjectID("background"), ) self._all_objs.append(self.bg) # Scrolling container old_y = getattr(getattr(self, "scrolling_container", None), "cur_y", 0) self.scrolling_container = CustomScroll( relative_rect=pygame.Rect(0, 0, *self._size), manager=self, object_id=pygame_gui.core.ObjectID("scroll_container"), ) self.scrolling_container.num_elems = len(self.available_bots) scrolling_size = (self._size[0] / 4 + self._size[0] / 5, self._size[1] * 0.9 - min(self._size[1] / 6, 90)) # Setting dimensions and positions on a UIScrollingContainer seems buggy. This works. self.scrolling_container.set_dimensions(scrolling_size) self.scrolling_container.set_position(scrolling_size) self.scrolling_container.cur_y = old_y self.scrolling_container.set_scroll(old_y) self._all_objs.append(self.scrolling_container) button_size = self._size[0] / 4, 60 info_size = self._size[0] / 4 - 20, 15 bot_rect = lambda i: (self._size[0] / 10, self._size[1] / 10 + i * button_size[1] * 1.5) info_rect = lambda b_r: ( b_r[0] + button_size[0] - info_size[0] - 10, b_r[1] + button_size[1] - info_size[1] - 5, ) self.bot_buttons = [] self.bot_descriptions = [] for i, (show, bot, rel_dir, filename) in enumerate(self.available_bots): self.bot_buttons.append( pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*bot_rect(i), *button_size), text=show, manager=self, container=self.scrolling_container, object_id=pygame_gui.core.ObjectID( show + "-" + str(i), "list_button_highlighted" if i == self.bot_index else "list_button"), )) self.addButtonEvent(show + "-" + str(i), self.setBotIndex, i) self.bot_descriptions.append( pygame_gui.elements.UILabel( relative_rect=pygame.Rect(*info_rect(bot_rect(i)), *info_size), text=rel_dir, manager=self, container=self.scrolling_container, object_id=pygame_gui.core.ObjectID( show + "-dir-" + str(i), "button_info_selected" if i == self.bot_index else "button_info"), )) self._all_objs.extend(self.bot_buttons) self._all_objs.extend(self.bot_descriptions) preview_size = self._size[0] / 4, self._size[1] / 4 preview_size = ( min(preview_size[0], (preview_size[1] * 4) // 3), min(preview_size[1], (preview_size[0] * 3) // 4), ) try: if self.bot_index >= len(self.available_bots): self.bot_index = -1 if self.bot_index == -1: image = pygame.Surface(preview_size) image.fill(pygame.Color(self.bg.background_colour)) else: with open( os.path.join(self.available_bots[self.bot_index][1], "config.bot"), "r") as f: config = yaml.safe_load(f) bot_preview = os.path.join( self.available_bots[self.bot_index][1], config.get("preview_path", "preview.png")) image = pygame.image.load(bot_preview) except Exception as e: sentry_sdk.capture_exception(e) self.setBotIndex(-1) self.addErrorDialog( '<font color="#cc0000">The bot you have selected has some internal errors EV3Sim cannot resolve.</font><br><br>' + "If you'd like to fix this, then try manually editing the bot file in a text editor." ) return if image.get_size() != preview_size: image = pygame.transform.smoothscale( image, [int(v) for v in preview_size]) self.preview_image = pygame_gui.elements.UIImage( relative_rect=pygame.Rect(self._size[0] * 0.9 - preview_size[0], self._size[1] * 0.1, *preview_size), image_surface=image, manager=self, object_id=pygame_gui.core.ObjectID("preview-image"), ) self._all_objs.append(self.preview_image) if len(self.bot_keys) == 0: code_size = preview_size[0] * 0.4, preview_size[1] * 0.4 code_button_pos = ( self._size[0] * 0.9 - code_size[0] - 10, self._size[1] * 0.1 + preview_size[1] + 10, ) code_icon_size = code_size[1] * 0.6, code_size[1] * 0.6 self.code_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*code_button_pos, *code_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("bot-code", "settings_buttons"), ) self.addButtonEvent("bot-code", self.clickCode) if not self.code_enable: self.code_button.disable() code_icon_path = find_abs("ui/code.png", allowed_areas=asset_locations()) self.code_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(code_button_pos, code_size, code_icon_size), *code_icon_size), image_surface=pygame.image.load(code_icon_path), manager=self, object_id=pygame_gui.core.ObjectID("code-icon"), ) self._all_objs.append(self.code_button) self._all_objs.append(self.code_icon) edit_button_pos = ( self._size[0] * 0.9 - preview_size[0], self._size[1] * 0.1 + preview_size[1] + 10, ) self.edit_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*edit_button_pos, *code_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("bot-edit", "settings_buttons"), ) self.addButtonEvent("bot-edit", self.clickEdit) if not self.edit_enable: self.edit_button.disable() edit_icon_path = find_abs("ui/edit.png", allowed_areas=asset_locations()) self.edit_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(edit_button_pos, code_size, code_icon_size), *code_icon_size), image_surface=pygame.image.load(edit_icon_path), manager=self, object_id=pygame_gui.core.ObjectID("edit-icon"), ) self._all_objs.append(self.edit_button) self._all_objs.append(self.edit_icon) new_size = self._size[0] / 8, min(self._size[1] / 6, 90) new_icon_size = new_size[1] * 0.6, new_size[1] * 0.6 new_bot_pos = (bot_rect(0)[0] + button_size[0] - new_size[0], self._size[1] * 0.9 - new_size[1]) self.new_bot = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*new_bot_pos, *new_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("new_bot", "action_button"), ) self.addButtonEvent("new_bot", self.clickNew) new_bot_path = find_abs("ui/add.png", allowed_areas=asset_locations()) self.new_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(new_bot_pos, new_size, new_icon_size), *new_icon_size), image_surface=pygame.image.load(new_bot_path), manager=self, object_id=pygame_gui.core.ObjectID("new_bot-icon"), ) self._all_objs.append(self.new_bot) self._all_objs.append(self.new_icon) remove_bot_pos = (bot_rect(0)[0], self._size[1] * 0.9 - new_size[1]) self.remove_bot = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*remove_bot_pos, *new_size), text="", manager=self, object_id=pygame_gui.core.ObjectID("remove_bot", "cancel-changes"), ) self.addButtonEvent("remove_bot", self.clickRemove) if not self.remove_enable: self.remove_bot.disable() remove_bot_path = find_abs("ui/bin.png", allowed_areas=asset_locations()) self.remove_icon = pygame_gui.elements.UIImage( relative_rect=pygame.Rect( *self.iconPos(remove_bot_pos, new_size, new_icon_size), *new_icon_size), image_surface=pygame.image.load(remove_bot_path), manager=self, object_id=pygame_gui.core.ObjectID("remove_bot-icon"), ) self._all_objs.append(self.remove_bot) self._all_objs.append(self.remove_icon) super().generateObjects() else: # Bot key locations, for selecting bots in batch files. self.bot_loc_spots = [] for i in range(len(self.bot_keys)): if i == self.key_index: self.bot_loc_spots.append( self.createBotImage(i, bg=pygame.Color("#80b918"))) else: self.bot_loc_spots.append(self.createBotImage(i)) self.sizeBotImage(i, big_mode=len(self.bot_keys) == 1) img = self.preview_images[i] if img is None: continue if img.get_size() != self.bot_loc_spots[i].rect.size: img = pygame.transform.smoothscale( img, (self.bot_loc_spots[i].rect.width, self.bot_loc_spots[i].rect.height)) self.bot_loc_spots[i].set_image(img) self._all_objs.extend(self.bot_loc_spots) select_size = (self._size[0] / 4 - 20) / 2, min( self._size[1] / 4, 120) select_button_pos = (self._size[0] * 0.9 - select_size[0] * 2 - 15, self._size[1] * 0.9 - select_size[1]) self.select_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*select_button_pos, *select_size), text="SELECT", manager=self, object_id=pygame_gui.core.ObjectID("select-bot", "action_button"), ) self.addButtonEvent("select-bot", self.clickSelect) if not self.select_enable: self.select_button.disable() self._all_objs.append(self.select_button) done_size = (self._size[0] / 4 - 20) / 2, min( self._size[1] / 4, 120) done_button_pos = (self._size[0] * 0.9 - select_size[0] - 5, self._size[1] * 0.9 - select_size[1]) self.done_button = pygame_gui.elements.UIButton( relative_rect=pygame.Rect(*done_button_pos, *done_size), text="DONE", manager=self, object_id=pygame_gui.core.ObjectID("select-done", "action_button"), ) self.addButtonEvent("select-done", self.clickDone) if self.key_index == 0: self.done_button.disable() self._all_objs.append(self.done_button) super().generateObjects()