コード例 #1
0
def onClickMapEditor(filename):
    from ev3sim.visual.manager import ScreenObjectManager

    ScreenObjectManager.instance.pushScreen(
        ScreenObjectManager.SCREEN_RESCUE_EDIT,
        batch_file=find_abs(f"{filename}.sim", batch_locations()),
    )
コード例 #2
0
 def clickSimBots(self, preset):
     abs_path = find_abs(preset, allowed_areas=preset_locations())
     with open(abs_path, "r") as f:
         preset_config = yaml.safe_load(f)
     sim_path = find_abs(preset_config["sim_location"],
                         allowed_areas=batch_locations())
     ScreenObjectManager.instance.pushScreen(
         ScreenObjectManager.SCREEN_BOTS,
         batch_file=sim_path,
     )
コード例 #3
0
    def clickSimSettings(self, preset):
        import importlib

        abs_path = find_abs(preset, allowed_areas=preset_locations())
        with open(abs_path, "r") as f:
            preset_config = yaml.safe_load(f)
        sim_path = find_abs(preset_config["sim_location"],
                            allowed_areas=batch_locations())
        mname, cname = preset_config["visual_settings"].rsplit(".", 1)
        klass = getattr(importlib.import_module(mname), cname)
        ScreenObjectManager.instance.pushScreen(
            ScreenObjectManager.SCREEN_SETTINGS,
            file=sim_path,
            settings=klass,
            allows_filename_change=False,
            extension="sim",
        )
コード例 #4
0
    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()
コード例 #5
0
    def playSim(self, preset):
        abs_path = find_abs(preset, allowed_areas=preset_locations())
        with open(abs_path, "r") as f:
            preset_config = yaml.safe_load(f)
        sim_path = find_abs(preset_config["sim_location"],
                            allowed_areas=batch_locations())
        with open(sim_path, "r") as f:
            sim_config = yaml.safe_load(f)
        to_remove = []
        for index in range(len(sim_config["bots"])):
            # Try loading this bot.
            try:
                with open(
                        os.path.join(
                            find_abs(sim_config["bots"][index],
                                     bot_locations()), "config.bot"),
                        "r") as f:
                    bot_config = yaml.safe_load(f)
                if not BotValidator.validate_json(bot_config):
                    to_remove.append(index)
                if bot_config.get("type", "python") == "python":
                    fname = bot_config.get("script", "code.py")
                else:
                    fname = bot_config.get("script", "program.ev3")
                if not os.path.exists(
                        os.path.join(
                            find_abs(sim_config["bots"][index],
                                     bot_locations()), fname)):

                    def action():
                        with open(
                                os.path.join(
                                    find_abs(sim_config["bots"][index],
                                             bot_locations()), fname),
                                "w") as f:
                            f.write("# Put your code here!\n")

                    ScreenObjectManager.instance.forceCloseError(
                        f"Your bot {sim_config['bots'][index]} does not contain the file {fname}. You may have renamed or deleted it by accident. In order to use this bot, you need to add this file back. Click \"Add {fname}\" to create this file, or do it manually.",
                        (f"Add {fname}", action),
                    )
                    return
            except:
                to_remove.append(index)
        if to_remove:
            for index in to_remove[::-1]:
                del sim_config["bots"][index]
            with open(sim_path, "w") as f:
                f.write(yaml.dump(sim_config))
        if not sim_config["bots"]:
            # We cannot play, there no are valid bots.
            return ScreenObjectManager.instance.pushScreen(
                ScreenObjectManager.SCREEN_BOTS,
                batch_file=sim_path,
                next=ScreenObjectManager.instance.SCREEN_SIM,
                next_kwargs={"batch": sim_path},
            )
        return ScreenObjectManager.instance.pushScreen(
            ScreenObjectManager.instance.SCREEN_SIM,
            batch=sim_path,
        )
コード例 #6
0
    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()