Esempio n. 1
0
    def __init__(self, parent):
        super().__init__(parent)

        self.field_cursor = FieldCursor(
            self.get_data,
            self.add_pre_history,
            self.add_post_history,
            MAX_SOUND_LENGTH,
            MAX_SOUND_LENGTH,
            4,
        )
        self.octave = 2
        self._is_playing = False
        self._play_pos = -1
        self._history_data = None
        self._sound_picker = NumberPicker(self, 45, 17, 0,
                                          pyxel.SOUND_BANK_COUNT - 1, 0)
        self._speed_picker = NumberPicker(self, 105, 17, 1, 99,
                                          pyxel.sound(0).speed)
        self._play_button = ImageButton(self, 185, 17, 3, EDITOR_IMAGE_X + 126,
                                        EDITOR_IMAGE_Y)
        self._stop_button = ImageButton(self,
                                        195,
                                        17,
                                        3,
                                        EDITOR_IMAGE_X + 135,
                                        EDITOR_IMAGE_Y,
                                        is_enabled=False)
        self._loop_button = ImageToggleButton(self, 205, 17, 3,
                                              EDITOR_IMAGE_X + 144,
                                              EDITOR_IMAGE_Y)
        self._piano_keyboard = PianoKeyboard(self)
        self._piano_roll = PianoRoll(self)
        self._sound_field = SoundField(self)
        self._left_octave_bar = OctaveBar(self, 12, 25)
        self._right_octave_bar = OctaveBar(self, 224, 25)

        self.add_event_handler("undo", self.__on_undo)
        self.add_event_handler("redo", self.__on_redo)
        self.add_event_handler("hide", self.__on_hide)
        self.add_event_handler("update", self.__on_update)
        self.add_event_handler("draw", self.__on_draw)
        self._sound_picker.add_event_handler("change",
                                             self.__on_sound_picker_change)
        self._speed_picker.add_event_handler("change",
                                             self.__on_speed_picker_change)
        self._play_button.add_event_handler("press",
                                            self.__on_play_button_press)
        self._stop_button.add_event_handler("press",
                                            self.__on_stop_button_press)
        self._play_button.add_event_handler("mouse_hover",
                                            self.__on_play_button_mouse_hover)
        self._stop_button.add_event_handler("mouse_hover",
                                            self.__on_stop_button_mouse_hover)
        self._loop_button.add_event_handler("mouse_hover",
                                            self.__on_loop_button_mouse_hover)
        self.add_number_picker_help(self._sound_picker)
        self.add_number_picker_help(self._speed_picker)
Esempio n. 2
0
    def __init__(self, parent):
        super().__init__(parent)

        self._music_picker = NumberPicker(self, 45, 17, 0, AUDIO_MUSIC_COUNT - 1, 0)
        self._play_button = ImageButton(self, 190, 17, 3, 126, 16)
        self._stop_button = ImageButton(self, 200, 17, 3, 135, 16)
        self._loop_button = ImageButton(self, 210, 17, 3, 144, 16)

        self.add_event_handler("draw", self.__on_draw)
Esempio n. 3
0
    def __init__(self, parent):
        super().__init__(parent)

        self._music_picker = NumberPicker(self, 45, 17, 0,
                                          AUDIO_MUSIC_COUNT - 1, 0)
        self._play_button = ImageButton(self, 185, 17, 3, EDITOR_IMAGE_X + 126,
                                        EDITOR_IMAGE_Y)
        self._stop_button = ImageButton(self, 195, 17, 3, EDITOR_IMAGE_X + 135,
                                        EDITOR_IMAGE_Y)
        self._loop_button = ImageButton(self, 205, 17, 3, EDITOR_IMAGE_X + 144,
                                        EDITOR_IMAGE_Y)

        self.add_event_handler("draw", self.__on_draw)
Esempio n. 4
0
    def __init__(self, parent):
        super().__init__(parent)

        self.cursor_x = 0
        self.cursor_y = 0
        self.octave = 2
        self._play_info = SoundEditor.PlayInfo()
        self._history_data = None
        self._sound_picker = NumberPicker(self, 45, 17, 0,
                                          AUDIO_SOUND_COUNT - 1, 0)
        self._speed_picker = NumberPicker(self, 105, 17, 1, 99,
                                          pyxel.sound(0).speed)
        self._play_button = ImageButton(self, 185, 17, 3, EDITOR_IMAGE_X + 126,
                                        EDITOR_IMAGE_Y)
        self._stop_button = ImageButton(self,
                                        195,
                                        17,
                                        3,
                                        EDITOR_IMAGE_X + 135,
                                        EDITOR_IMAGE_Y,
                                        is_enabled=False)
        self._loop_button = ImageToggleButton(self, 205, 17, 3,
                                              EDITOR_IMAGE_X + 144,
                                              EDITOR_IMAGE_Y)
        self._piano_keyboard = PianoKeyboard(self)
        self._piano_roll = PianoRoll(self)
        self._sound_input = SoundInput(self)
        self._left_octave_bar = OctaveBar(self, 12, 25)
        self._right_octave_bar = OctaveBar(self, 224, 25)

        self.add_event_handler("undo", self.__on_undo)
        self.add_event_handler("redo", self.__on_redo)
        self.add_event_handler("update", self.__on_update)
        self.add_event_handler("draw", self.__on_draw)
        self._sound_picker.add_event_handler("change",
                                             self.__on_sound_picker_change)
        self._speed_picker.add_event_handler("change",
                                             self.__on_speed_picker_change)
        self._play_button.add_event_handler("press",
                                            self.__on_play_button_press)
        self._stop_button.add_event_handler("press",
                                            self.__on_stop_button_press)
        self._play_button.add_event_handler("mouse_hover",
                                            self.__on_play_button_mouse_hover)
        self._stop_button.add_event_handler("mouse_hover",
                                            self.__on_stop_button_mouse_hover)
        self._loop_button.add_event_handler("mouse_hover",
                                            self.__on_loop_button_mouse_hover)
        self.add_number_picker_help(self._sound_picker)
        self.add_number_picker_help(self._speed_picker)
Esempio n. 5
0
    def __init__(self, parent):
        super().__init__(parent)

        self._is_playing = False
        self._play_pos = [0 for _ in range(MUSIC_CHANNEL_COUNT)]
        self.field_cursor = FieldCursor(
            self.get_data,
            self.add_pre_history,
            self.add_post_history,
            MAX_MUSIC_LENGTH,
            16,
            MUSIC_CHANNEL_COUNT,
        )
        self._music_picker = NumberPicker(self, 45, 17, 0,
                                          MUSIC_BANK_COUNT - 1, 0)
        self._play_button = ImageButton(self, 185, 17, 3, EDITOR_IMAGE_X + 126,
                                        EDITOR_IMAGE_Y)
        self._stop_button = ImageButton(self, 195, 17, 3, EDITOR_IMAGE_X + 135,
                                        EDITOR_IMAGE_Y)
        self._loop_button = ImageToggleButton(self, 205, 17, 3,
                                              EDITOR_IMAGE_X + 144,
                                              EDITOR_IMAGE_Y)
        self._music_field = [
            MusicField(self, 11, 29 + i * 25, i) for i in range(4)
        ]
        self._sound_selector = SoundSelector(self)

        self.add_event_handler("undo", self.__on_undo)
        self.add_event_handler("redo", self.__on_redo)
        self.add_event_handler("hide", self.__on_hide)
        self.add_event_handler("update", self.__on_update)
        self.add_event_handler("draw", self.__on_draw)
        self._play_button.add_event_handler("press",
                                            self.__on_play_button_press)
        self._stop_button.add_event_handler("press",
                                            self.__on_stop_button_press)
        self._play_button.add_event_handler("mouse_hover",
                                            self.__on_play_button_mouse_hover)
        self._stop_button.add_event_handler("mouse_hover",
                                            self.__on_stop_button_mouse_hover)
        self._loop_button.add_event_handler("mouse_hover",
                                            self.__on_loop_button_mouse_hover)
        self.add_number_picker_help(self._music_picker)
Esempio n. 6
0
File: app.py Progetto: yyq90/pyxel
    def __init__(self, resource_file):
        resource_file = os.path.join(os.getcwd(), resource_file)
        root, ext = os.path.splitext(resource_file)
        if ext != ".pyxel":
            resource_file += ".pyxel"

        pyxel.init(
            EDITOR_WIDTH,
            EDITOR_HEIGHT,
            caption="Pyxel Editor - {}".format(resource_file),
        )

        try:
            pyxel.load(resource_file)
        except FileNotFoundError:
            pass

        super().__init__(None, 0, 0, pyxel.width, pyxel.height)

        self._resource_file = resource_file
        self._editor_list = [
            ImageEditor(self),
            TileMapEditor(self),
            SoundEditor(self),
            MusicEditor(self),
        ]
        self._editor_button = RadioButton(self, 1, 1, 3, 0, 16, 4, EDITOR_IMAGE)
        self._undo_button = ImageButton(self, 48, 1, 3, 36, 16)
        self._redo_button = ImageButton(self, 57, 1, 3, 45, 16)
        self._save_button = ImageButton(self, 75, 1, 3, 54, 16)
        self.help_message = ""

        self._editor_button.add_event_handler(
            "change", lambda value: self.set_editor(value)
        )
        self.add_event_handler("update", self.__on_update)
        self.add_event_handler("draw", self.__on_draw)
        self._undo_button.add_event_handler("press", self.__on_undo_press)
        self._redo_button.add_event_handler("press", self.__on_redo_press)
        self._save_button.add_event_handler("press", self.__on_save_press)
        self._editor_button.add_event_handler(
            "mouse_hover", self.__editor_button_on_mouse_hover
        )
        self._undo_button.add_event_handler(
            "mouse_hover", self.__undo_button_on_mouse_hover
        )
        self._redo_button.add_event_handler(
            "mouse_hover", self.__redo_button_on_mouse_hover
        )
        self._save_button.add_event_handler(
            "mouse_hover", self.__save_button_on_mouse_hover
        )

        self.set_editor(0)

        image_file = os.path.join(os.path.dirname(__file__), "assets", "editor.png")
        pyxel.image(3, system=True).load(0, 16, image_file)

        pyxel.run(self.update_widgets, self.draw_widgets)
Esempio n. 7
0
    def __init__(self, resource_file):
        resource_file = os.path.join(os.getcwd(), resource_file)
        root, ext = os.path.splitext(resource_file)
        if ext != ".pyxel":
            resource_file += ".pyxel"

        pyxel.init(
            EDITOR_WIDTH,
            EDITOR_HEIGHT,
            caption="Pyxel Editor - {}".format(resource_file),
        )

        try:
            pyxel.load(resource_file)
        except FileNotFoundError:
            pass

        self._resource_file = resource_file
        self._root_widget = Widget(None, 0, 0, 0, 0)

        self._screen_list = [
            ImageEditor(self._root_widget),
            TileMapEditor(self._root_widget),
            SoundEditor(self._root_widget),
            MusicEditor(self._root_widget),
        ]

        self._screen_button = RadioButton(self._root_widget, 3, 1, 3, 3, 13, 4)
        self._screen_button.add_event_handler(
            "change", lambda value: self.set_screen(value))
        self.set_screen(0)

        self._undo_button = ImageButton(self._root_widget, 48, 1, 3, 48, 13)
        self._undo_button.add_event_handler("press", self.__on_undo_press)

        self._redo_button = ImageButton(self._root_widget, 57, 1, 3, 57, 13)
        self._redo_button.add_event_handler("press", self.__on_redo_press)

        self._save_button = ImageButton(self._root_widget, 75, 1, 3, 75, 13)
        self._save_button.add_event_handler("press", self.__on_save_press)

        pyxel.run(self.update, self.draw)
Esempio n. 8
0
class EditorApp:
    def __init__(self, resource_file):
        resource_file = os.path.join(os.getcwd(), resource_file)
        root, ext = os.path.splitext(resource_file)
        if ext != ".pyxel":
            resource_file += ".pyxel"

        pyxel.init(
            EDITOR_WIDTH,
            EDITOR_HEIGHT,
            caption="Pyxel Editor - {}".format(resource_file),
        )

        try:
            pyxel.load(resource_file)
        except FileNotFoundError:
            pass

        self._resource_file = resource_file
        self._root_widget = Widget(None, 0, 0, 0, 0)

        self._screen_list = [
            ImageEditor(self._root_widget),
            TileMapEditor(self._root_widget),
            SoundEditor(self._root_widget),
            MusicEditor(self._root_widget),
        ]

        self._screen_button = RadioButton(self._root_widget, 3, 1, 3, 3, 13, 4)
        self._screen_button.add_event_handler(
            "change", lambda value: self.set_screen(value))
        self.set_screen(0)

        self._undo_button = ImageButton(self._root_widget, 48, 1, 3, 48, 13)
        self._undo_button.add_event_handler("press", self.__on_undo_press)

        self._redo_button = ImageButton(self._root_widget, 57, 1, 3, 57, 13)
        self._redo_button.add_event_handler("press", self.__on_redo_press)

        self._save_button = ImageButton(self._root_widget, 75, 1, 3, 75, 13)
        self._save_button.add_event_handler("press", self.__on_save_press)

        pyxel.run(self.update, self.draw)

    def set_screen(self, screen):
        self._screen_button.value = screen

        for i, widget in enumerate(self._screen_list):
            widget.is_visible = i == screen

    def update(self):
        if pyxel.btn(pyxel.KEY_LEFT_ALT) or pyxel.btn(pyxel.KEY_RIGHT_ALT):
            screen = self._screen_button.value
            screen_count = len(self._screen_list)

            if pyxel.btnp(pyxel.KEY_LEFT):
                self.set_screen((screen - 1) % screen_count)
            elif pyxel.btnp(pyxel.KEY_RIGHT):
                self.set_screen((screen + 1) % screen_count)

        screen = self._screen_list[self._screen_button.value]
        self._undo_button.is_enabled = screen.can_undo
        self._redo_button.is_enabled = screen.can_redo

        if pyxel.btn(pyxel.KEY_CONTROL):
            if screen.can_undo and pyxel.btnp(pyxel.KEY_S):
                self._save_button.press()
            elif screen.can_undo and pyxel.btnp(pyxel.KEY_Z):
                self._undo_button.press()
            elif screen.can_redo and pyxel.btnp(pyxel.KEY_Y):
                self._redo_button.press()

        Widget.update(self._root_widget)

    def draw(self):
        pyxel.cls(6)
        Widget.draw(self._root_widget)

    def __on_undo_press(self):
        self._screen_list[self._screen_button.value].undo()

    def __on_redo_press(self):
        self._screen_list[self._screen_button.value].redo()

    def __on_save_press(self):
        pyxel.save(self._resource_file)
Esempio n. 9
0
class SoundEditor(Editor):
    def __init__(self, parent):
        super().__init__(parent)

        self.field_cursor = FieldCursor(
            self.get_data,
            self.add_pre_history,
            self.add_post_history,
            SOUND_MAX_LENGTH,
            SOUND_MAX_LENGTH,
            4,
        )
        self.octave = 2
        self._is_playing = False
        self._play_pos = None
        self._history_data = None
        self._sound_picker = NumberPicker(self, 45, 17, 0, AUDIO_SOUND_COUNT - 2, 0)
        self._speed_picker = NumberPicker(self, 105, 17, 1, 99, pyxel.sound(0).speed)
        self._play_button = ImageButton(
            self, 185, 17, 3, EDITOR_IMAGE_X + 126, EDITOR_IMAGE_Y
        )
        self._stop_button = ImageButton(
            self, 195, 17, 3, EDITOR_IMAGE_X + 135, EDITOR_IMAGE_Y, is_enabled=False
        )
        self._loop_button = ImageToggleButton(
            self, 205, 17, 3, EDITOR_IMAGE_X + 144, EDITOR_IMAGE_Y
        )
        self._piano_keyboard = PianoKeyboard(self)
        self._piano_roll = PianoRoll(self)
        self._sound_field = SoundField(self)
        self._left_octave_bar = OctaveBar(self, 12, 25)
        self._right_octave_bar = OctaveBar(self, 224, 25)

        self.add_event_handler("undo", self.__on_undo)
        self.add_event_handler("redo", self.__on_redo)
        self.add_event_handler("hide", self.__on_hide)
        self.add_event_handler("update", self.__on_update)
        self.add_event_handler("draw", self.__on_draw)
        self._sound_picker.add_event_handler("change", self.__on_sound_picker_change)
        self._speed_picker.add_event_handler("change", self.__on_speed_picker_change)
        self._play_button.add_event_handler("press", self.__on_play_button_press)
        self._stop_button.add_event_handler("press", self.__on_stop_button_press)
        self._play_button.add_event_handler(
            "mouse_hover", self.__on_play_button_mouse_hover
        )
        self._stop_button.add_event_handler(
            "mouse_hover", self.__on_stop_button_mouse_hover
        )
        self._loop_button.add_event_handler(
            "mouse_hover", self.__on_loop_button_mouse_hover
        )
        self.add_number_picker_help(self._sound_picker)
        self.add_number_picker_help(self._speed_picker)

    @property
    def keyboard_note(self):
        return self._piano_keyboard.note

    @property
    def is_playing(self):
        return self._is_playing

    @property
    def play_pos(self):
        return self._play_pos

    def get_data(self, index):
        sound = pyxel.sound(self._sound_picker.value)

        if index == 0:
            data = sound.note
        elif index == 1:
            data = sound.tone
        elif index == 2:
            data = sound.volume
        elif index == 3:
            data = sound.effect

        return data

    def add_pre_history(self, x, y):
        self._history_data = data = {}
        data["sound"] = self._sound_picker.value
        data["cursor_before"] = (x, y)
        data["before"] = self.field_cursor.data.copy()

    def add_post_history(self, x, y):
        data = self._history_data
        data["cursor_after"] = (x, y)
        data["after"] = self.field_cursor.data.copy()

        if data["before"] != data["after"]:
            self.add_history(self._history_data)

    def _play(self):
        self._is_playing = True
        self._play_pos = 0
        self._sound_picker.is_enabled = False
        self._speed_picker.is_enabled = False
        self._play_button.is_enabled = False
        self._stop_button.is_enabled = True
        self._loop_button.is_enabled = False

        pyxel.play(0, self._sound_picker.value, loop=self._loop_button.value)

    def _stop(self):
        self._is_playing = None
        self._play_pos = None
        self._sound_picker.is_enabled = True
        self._speed_picker.is_enabled = True
        self._play_button.is_enabled = True
        self._stop_button.is_enabled = False
        self._loop_button.is_enabled = True

        pyxel.stop(0)

    def __on_undo(self, data):
        self._sound_picker.value = data["sound"]
        self.field_cursor.move(*data["cursor_before"])
        self.field_cursor.data[:] = data["before"]

    def __on_redo(self, data):
        self._sound_picker.value = data["sound"]
        self.field_cursor.move(*data["cursor_after"])
        self.field_cursor.data[:] = data["after"]

    def __on_hide(self):
        self._stop()

    def __on_update(self):
        channel = pyxel._app._audio_player._channel_list[0]
        self._is_playing = channel._is_playing
        self._play_pos = (
            int(channel._time / channel._one_note_time) if channel._is_playing else None
        )

        if pyxel.btnp(pyxel.KEY_SPACE):
            if self._is_playing:
                self._stop_button.press()
            else:
                self._play_button.press()

        if self._is_playing:
            return

        if not self._play_button.is_enabled:
            self._stop()

        if self._loop_button.is_enabled and pyxel.btnp(pyxel.KEY_L):
            self._loop_button.press()

        if pyxel.btnp(pyxel.KEY_PAGE_UP):
            self.octave = min(self.octave + 1, 3)

        if pyxel.btnp(pyxel.KEY_PAGE_DOWN):
            self.octave = max(self.octave - 1, 0)

        self.field_cursor.process_input()

    def __on_draw(self):
        self.draw_panel(11, 16, 218, 157)
        pyxel.text(23, 18, "SOUND", 6)
        pyxel.text(83, 18, "SPEED", 6)

    def __on_sound_picker_change(self, value):
        sound = pyxel.sound(value)
        self._speed_picker.value = sound.speed

    def __on_speed_picker_change(self, value):
        sound = pyxel.sound(self._sound_picker.value)
        sound.speed = value

    def __on_play_button_press(self):
        self._play()

    def __on_stop_button_press(self):
        self._stop()

    def __on_play_button_mouse_hover(self, x, y):
        self.parent.help_message = "PLAY:SPACE"

    def __on_stop_button_mouse_hover(self, x, y):
        self.parent.help_message = "STOP:SPACE"

    def __on_loop_button_mouse_hover(self, x, y):
        self.parent.help_message = "LOOP:L"
Esempio n. 10
0
class App(Widget):
    def __init__(self, resource_file):
        resource_file = os.path.join(os.getcwd(), resource_file)
        root, ext = os.path.splitext(resource_file)
        if ext != ".pyxel":
            resource_file += ".pyxel"

        pyxel.init(APP_WIDTH,
                   APP_HEIGHT,
                   caption="Pyxel Editor - {}".format(resource_file))

        try:
            pyxel.load(resource_file)
        except FileNotFoundError:
            pass

        super().__init__(None, 0, 0, pyxel.width, pyxel.height)

        self._resource_file = resource_file
        self._editor_list = [
            ImageEditor(self),
            TileMapEditor(self),
            SoundEditor(self),
            MusicEditor(self),
        ]
        self._editor_button = RadioButton(self, 1, 1, 3, EDITOR_IMAGE_X,
                                          EDITOR_IMAGE_Y, 4, 0)
        self._undo_button = ImageButton(self, 48, 1, 3, EDITOR_IMAGE_X + 36,
                                        EDITOR_IMAGE_Y)
        self._redo_button = ImageButton(self, 57, 1, 3, EDITOR_IMAGE_X + 45,
                                        EDITOR_IMAGE_Y)
        self._save_button = ImageButton(self, 75, 1, 3, EDITOR_IMAGE_X + 54,
                                        EDITOR_IMAGE_Y)
        self.help_message = ""

        self._editor_button.add_event_handler(
            "change", lambda value: self.set_editor(value))
        self.add_event_handler("update", self.__on_update)
        self.add_event_handler("draw", self.__on_draw)
        self._undo_button.add_event_handler("press",
                                            self.__on_undo_button_press)
        self._undo_button.add_event_handler("repeat",
                                            self.__on_undo_button_press)
        self._redo_button.add_event_handler("press",
                                            self.__on_redo_button_press)
        self._redo_button.add_event_handler("repeat",
                                            self.__on_redo_button_press)
        self._save_button.add_event_handler("press",
                                            self.__on_save_button_press)
        self._editor_button.add_event_handler(
            "mouse_hover", self.__on_editor_button_mouse_hover)
        self._undo_button.add_event_handler("mouse_hover",
                                            self.__on_undo_button_mouse_hover)
        self._redo_button.add_event_handler("mouse_hover",
                                            self.__on_redo_button_mouse_hover)
        self._save_button.add_event_handler("mouse_hover",
                                            self.__on_save_button_mouse_hover)

        self.set_editor(0)

        image_file = os.path.join(os.path.dirname(__file__), "assets",
                                  EDITOR_IMAGE_NAME)
        pyxel.image(3, system=True).load(EDITOR_IMAGE_X, EDITOR_IMAGE_Y,
                                         image_file)

        pyxel.mouse(True)

        pyxel.run(self.update_widgets, self.draw_widgets)

    def set_editor(self, editor):
        self._editor_button.value = editor

        for i, widget in enumerate(self._editor_list):
            widget.is_visible = i == editor

    def __on_update(self):
        if pyxel.btn(pyxel.KEY_LEFT_ALT) or pyxel.btn(pyxel.KEY_RIGHT_ALT):
            editor = self._editor_button.value
            editor_count = len(self._editor_list)

            if pyxel.btnp(pyxel.KEY_LEFT):
                self.set_editor((editor - 1) % editor_count)
            elif pyxel.btnp(pyxel.KEY_RIGHT):
                self.set_editor((editor + 1) % editor_count)

        editor = self._editor_list[self._editor_button.value]
        self._undo_button.is_enabled = editor.can_undo
        self._redo_button.is_enabled = editor.can_redo

        if pyxel.btn(pyxel.KEY_CONTROL):
            if pyxel.btnp(pyxel.KEY_S):
                self._save_button.press()

            if editor.can_undo and pyxel.btnp(pyxel.KEY_Z):
                self._undo_button.press()

            if editor.can_redo and pyxel.btnp(pyxel.KEY_Y):
                self._redo_button.press()

    def __on_draw(self):
        pyxel.cls(WIDGET_BACKGROUND_COLOR)
        pyxel.rect(0, 0, 239, 8, WIDGET_PANEL_COLOR)
        pyxel.line(0, 9, 239, 9, WIDGET_SHADOW_COLOR)

        pyxel.text(93, 2, self.help_message, 13)
        self.help_message = ""

    def __on_undo_button_press(self):
        self._editor_list[self._editor_button.value].undo()

    def __on_redo_button_press(self):
        self._editor_list[self._editor_button.value].redo()

    def __on_save_button_press(self):
        pyxel.save(self._resource_file)

    def __on_editor_button_mouse_hover(self, x, y):
        self.help_message = "EDITOR:ALT+LEFT/RIGHT"

    def __on_undo_button_mouse_hover(self, x, y):
        self.help_message = "UNDO:CTRL+Z"

    def __on_redo_button_mouse_hover(self, x, y):
        self.help_message = "REDO:CTRL+Y"

    def __on_save_button_mouse_hover(self, x, y):
        self.help_message = "SAVE:CTRL+S"
Esempio n. 11
0
    def __init__(self, resource_file):
        resource_file = os.path.join(os.getcwd(), resource_file)
        root, ext = os.path.splitext(resource_file)
        if ext != ".pyxel":
            resource_file += ".pyxel"

        pyxel.init(
            APP_WIDTH, APP_HEIGHT, caption="Pyxel Editor - {}".format(resource_file)
        )
        pyxel.mouse(True)

        try:
            pyxel.load(resource_file)
        except FileNotFoundError:
            pass

        super().__init__(None, 0, 0, pyxel.width, pyxel.height)

        self._resource_file = resource_file
        self._editor_list = [
            ImageEditor(self),
            TileMapEditor(self),
            SoundEditor(self),
            MusicEditor(self),
        ]
        self._editor_button = RadioButton(
            self, 1, 1, 3, EDITOR_IMAGE_X, EDITOR_IMAGE_Y, 4, 0
        )
        self._undo_button = ImageButton(
            self, 48, 1, 3, EDITOR_IMAGE_X + 36, EDITOR_IMAGE_Y
        )
        self._redo_button = ImageButton(
            self, 57, 1, 3, EDITOR_IMAGE_X + 45, EDITOR_IMAGE_Y
        )
        self._save_button = ImageButton(
            self, 75, 1, 3, EDITOR_IMAGE_X + 54, EDITOR_IMAGE_Y
        )
        self.help_message = ""

        self._editor_button.add_event_handler(
            "change", lambda value: self._set_editor(value)
        )
        self.add_event_handler("update", self.__on_update)
        self.add_event_handler("draw", self.__on_draw)
        self._undo_button.add_event_handler("press", self.__on_undo_button_press)
        self._undo_button.add_event_handler("repeat", self.__on_undo_button_press)
        self._redo_button.add_event_handler("press", self.__on_redo_button_press)
        self._redo_button.add_event_handler("repeat", self.__on_redo_button_press)
        self._save_button.add_event_handler("press", self.__on_save_button_press)
        self._editor_button.add_event_handler(
            "mouse_hover", self.__on_editor_button_mouse_hover
        )
        self._undo_button.add_event_handler(
            "mouse_hover", self.__on_undo_button_mouse_hover
        )
        self._redo_button.add_event_handler(
            "mouse_hover", self.__on_redo_button_mouse_hover
        )
        self._save_button.add_event_handler(
            "mouse_hover", self.__on_save_button_mouse_hover
        )

        glfw.set_drop_callback(pyxel._app._window, self._drop_callback)
        image_file = os.path.join(
            os.path.dirname(__file__), "assets", EDITOR_IMAGE_NAME
        )
        pyxel.image(3, system=True).load(EDITOR_IMAGE_X, EDITOR_IMAGE_Y, image_file)

        self._set_editor(0)

        pyxel.run(self.update_widgets, self.draw_widgets)
Esempio n. 12
0
class MusicEditor(Editor):
    def __init__(self, parent):
        super().__init__(parent)

        self._is_playing = False
        self._play_pos = [0 for _ in range(pyxel.MUSIC_CHANNEL_COUNT)]
        self.field_cursor = FieldCursor(
            self.get_data,
            self.add_pre_history,
            self.add_post_history,
            MAX_MUSIC_LENGTH,
            16,
            pyxel.MUSIC_CHANNEL_COUNT,
        )
        self._music_picker = NumberPicker(self, 45, 17, 0,
                                          pyxel.MUSIC_BANK_COUNT - 1, 0)
        self._play_button = ImageButton(
            self,
            185,
            17,
            pyxel.IMAGE_BANK_FOR_SYSTEM,
            EDITOR_IMAGE_X + 126,
            EDITOR_IMAGE_Y,
        )
        self._stop_button = ImageButton(
            self,
            195,
            17,
            pyxel.IMAGE_BANK_FOR_SYSTEM,
            EDITOR_IMAGE_X + 135,
            EDITOR_IMAGE_Y,
        )
        self._loop_button = ImageToggleButton(
            self,
            205,
            17,
            pyxel.IMAGE_BANK_FOR_SYSTEM,
            EDITOR_IMAGE_X + 144,
            EDITOR_IMAGE_Y,
        )
        self._music_field = [
            MusicField(self, 11, 29 + i * 25, i) for i in range(4)
        ]
        self._sound_selector = SoundSelector(self)

        self.add_event_handler("undo", self.__on_undo)
        self.add_event_handler("redo", self.__on_redo)
        self.add_event_handler("hide", self.__on_hide)
        self.add_event_handler("update", self.__on_update)
        self.add_event_handler("draw", self.__on_draw)
        self._play_button.add_event_handler("press",
                                            self.__on_play_button_press)
        self._stop_button.add_event_handler("press",
                                            self.__on_stop_button_press)
        self._play_button.add_event_handler("mouse_hover",
                                            self.__on_play_button_mouse_hover)
        self._stop_button.add_event_handler("mouse_hover",
                                            self.__on_stop_button_mouse_hover)
        self._loop_button.add_event_handler("mouse_hover",
                                            self.__on_loop_button_mouse_hover)
        self.add_number_picker_help(self._music_picker)

    @property
    def music(self):
        return self._music_picker.value

    @property
    def is_playing(self):
        return self._is_playing

    def play_pos(self, ch):
        return self._play_pos[ch]

    def get_data(self, value):
        music = pyxel.music(self._music_picker.value)

        if value == 0:
            data = music.ch0
        elif value == 1:
            data = music.ch1
        elif value == 2:
            data = music.ch2
        elif value == 3:
            data = music.ch3

        return data

    def add_pre_history(self, x, y):
        self._history_data = data = {}
        data["music"] = self._music_picker.value
        data["cursor_before"] = (x, y)
        data["before"] = self.field_cursor.data[:]

    def add_post_history(self, x, y):
        data = self._history_data
        data["cursor_after"] = (x, y)
        data["after"] = self.field_cursor.data[:]

        if data["before"] != data["after"]:
            self.add_history(self._history_data)

    def _play(self):
        self._is_playing = True

        for i in range(pyxel.MUSIC_CHANNEL_COUNT):
            self._play_pos[i] = 0

        self._music_picker.is_enabled = False
        self._play_button.is_enabled = False
        self._stop_button.is_enabled = True
        self._loop_button.is_enabled = False

        pyxel.playm(self._music_picker.value, loop=self._loop_button.value)

    def _stop(self):
        self._is_playing = False

        for i in range(pyxel.MUSIC_CHANNEL_COUNT):
            self._play_pos[i] = -1

        self._music_picker.is_enabled = True
        self._play_button.is_enabled = True
        self._stop_button.is_enabled = False
        self._loop_button.is_enabled = True

        pyxel.stop()

    def __on_undo(self, data):
        self._music_picker.value = data["music"]
        self.field_cursor.move(*data["cursor_before"])
        self.field_cursor.data[:] = data["before"]

    def __on_redo(self, data):
        dat = data["after"]
        dat_len = len(dat)

        self._music_picker.value = data["music"]
        self.field_cursor.move(*data["cursor_after"])
        self.field_cursor.data[:dat_len] = dat
        self.field_cursor.data_lengh = dat_len

    def __on_hide(self):
        self._stop()

    def __on_update(self):
        if self._is_playing:
            self._is_playing = False

            for i in range(pyxel.MUSIC_CHANNEL_COUNT):
                if pyxel.play_pos(i) >= 0:
                    self._is_playing = True
                    play_pos = pyxel.play_pos(i)
                    self._play_pos[
                        i] = play_pos // 100 if play_pos >= 0 else -1
                else:
                    self._play_pos[i] = -1

        if pyxel.btnp(pyxel.KEY_SPACE):
            if self._is_playing:
                self._stop_button.press()
            else:
                self._play_button.press()

        if self._is_playing:
            return

        if not self._play_button.is_enabled:
            self._stop()

        if self._loop_button.is_enabled and pyxel.btnp(pyxel.KEY_L):
            self._loop_button.press()

        self.field_cursor.process_input()

    def __on_draw(self):
        self.draw_panel(11, 16, 218, 9)
        pyxel.text(23, 18, "MUSIC", 6)

    def __on_play_button_press(self):
        self._play()

    def __on_stop_button_press(self):
        self._stop()

    def __on_play_button_mouse_hover(self, x, y):
        self.parent.help_message = "PLAY:SPACE"

    def __on_stop_button_mouse_hover(self, x, y):
        self.parent.help_message = "STOP:SPACE"

    def __on_loop_button_mouse_hover(self, x, y):
        self.parent.help_message = "LOOP:L"
Esempio n. 13
0
    def __init__(self, resource_file):
        resource_file = os.path.join(os.getcwd(), resource_file)
        root, ext = os.path.splitext(resource_file)
        if ext != pyxel.RESOURCE_FILE_EXTENSION:
            resource_file += pyxel.RESOURCE_FILE_EXTENSION

        pyxel.init(
            APP_WIDTH, APP_HEIGHT, caption="Pyxel Editor - {}".format(resource_file)
        )
        pyxel.mouse(True)

        if os.path.exists(resource_file):
            pyxel.load(resource_file)

        if ext == ".pyxel":
            resource_file = root + pyxel.RESOURCE_FILE_EXTENSION

        super().__init__(None, 0, 0, pyxel.width, pyxel.height)

        self._resource_file = resource_file
        self._editor_list = [
            ImageEditor(self),
            TileMapEditor(self),
            SoundEditor(self),
            MusicEditor(self),
        ]
        self._editor_button = RadioButton(
            self,
            1,
            1,
            pyxel.IMAGE_BANK_FOR_SYSTEM,
            EDITOR_IMAGE_X,
            EDITOR_IMAGE_Y,
            4,
            0,
        )
        self._undo_button = ImageButton(
            self,
            48,
            1,
            pyxel.IMAGE_BANK_FOR_SYSTEM,
            EDITOR_IMAGE_X + 36,
            EDITOR_IMAGE_Y,
        )
        self._redo_button = ImageButton(
            self,
            57,
            1,
            pyxel.IMAGE_BANK_FOR_SYSTEM,
            EDITOR_IMAGE_X + 45,
            EDITOR_IMAGE_Y,
        )
        self._save_button = ImageButton(
            self,
            75,
            1,
            pyxel.IMAGE_BANK_FOR_SYSTEM,
            EDITOR_IMAGE_X + 54,
            EDITOR_IMAGE_Y,
        )
        self.help_message = ""

        self._editor_button.add_event_handler(
            "change", lambda value: self._set_editor(value)
        )
        self.add_event_handler("update", self.__on_update)
        self.add_event_handler("draw", self.__on_draw)
        self._undo_button.add_event_handler("press", self.__on_undo_button_press)
        self._undo_button.add_event_handler("repeat", self.__on_undo_button_press)
        self._redo_button.add_event_handler("press", self.__on_redo_button_press)
        self._redo_button.add_event_handler("repeat", self.__on_redo_button_press)
        self._save_button.add_event_handler("press", self.__on_save_button_press)
        self._editor_button.add_event_handler(
            "mouse_hover", self.__on_editor_button_mouse_hover
        )
        self._undo_button.add_event_handler(
            "mouse_hover", self.__on_undo_button_mouse_hover
        )
        self._redo_button.add_event_handler(
            "mouse_hover", self.__on_redo_button_mouse_hover
        )
        self._save_button.add_event_handler(
            "mouse_hover", self.__on_save_button_mouse_hover
        )

        image_file = os.path.join(
            os.path.dirname(__file__), "assets", EDITOR_IMAGE_NAME
        )
        pyxel.image(pyxel.IMAGE_BANK_FOR_SYSTEM, system=True).load(
            EDITOR_IMAGE_X, EDITOR_IMAGE_Y, image_file
        )

        self._set_editor(0)

        pyxel.run(self.update_widgets, self.draw_widgets)
Esempio n. 14
0
class SoundEditor(Editor):
    class PlayInfo:
        is_playing = False
        is_looping = False
        start_time = 0
        speed = 0
        length = 0

    def __init__(self, parent):
        super().__init__(parent)

        self.cursor_x = 0
        self.cursor_y = 0
        self.octave = 2
        self._play_info = SoundEditor.PlayInfo()
        self._history_data = None
        self._sound_picker = NumberPicker(self, 45, 17, 0,
                                          AUDIO_SOUND_COUNT - 1, 0)
        self._speed_picker = NumberPicker(self, 105, 17, 1, 99,
                                          pyxel.sound(0).speed)
        self._play_button = ImageButton(self, 185, 17, 3, EDITOR_IMAGE_X + 126,
                                        EDITOR_IMAGE_Y)
        self._stop_button = ImageButton(self,
                                        195,
                                        17,
                                        3,
                                        EDITOR_IMAGE_X + 135,
                                        EDITOR_IMAGE_Y,
                                        is_enabled=False)
        self._loop_button = ImageToggleButton(self, 205, 17, 3,
                                              EDITOR_IMAGE_X + 144,
                                              EDITOR_IMAGE_Y)
        self._piano_keyboard = PianoKeyboard(self)
        self._piano_roll = PianoRoll(self)
        self._sound_input = SoundInput(self)
        self._left_octave_bar = OctaveBar(self, 12, 25)
        self._right_octave_bar = OctaveBar(self, 224, 25)

        self.add_event_handler("undo", self.__on_undo)
        self.add_event_handler("redo", self.__on_redo)
        self.add_event_handler("update", self.__on_update)
        self.add_event_handler("draw", self.__on_draw)
        self._sound_picker.add_event_handler("change",
                                             self.__on_sound_picker_change)
        self._speed_picker.add_event_handler("change",
                                             self.__on_speed_picker_change)
        self._play_button.add_event_handler("press",
                                            self.__on_play_button_press)
        self._stop_button.add_event_handler("press",
                                            self.__on_stop_button_press)
        self._play_button.add_event_handler("mouse_hover",
                                            self.__on_play_button_mouse_hover)
        self._stop_button.add_event_handler("mouse_hover",
                                            self.__on_stop_button_mouse_hover)
        self._loop_button.add_event_handler("mouse_hover",
                                            self.__on_loop_button_mouse_hover)
        self.add_number_picker_help(self._sound_picker)
        self.add_number_picker_help(self._speed_picker)

    @property
    def sound(self):
        return self._sound_picker.value

    @property
    def speed(self):
        return self._speed_picker.value

    @property
    def sound_data(self):
        sound = pyxel.sound(self._sound_picker.value)

        if self.cursor_y == 0:
            data = sound.note
        elif self.cursor_y == 1:
            data = sound.tone
        elif self.cursor_y == 2:
            data = sound.volume
        elif self.cursor_y == 3:
            data = sound.effect

        return data

    @property
    def max_edit_x(self):
        return min(len(self.sound_data), SOUND_MAX_LENGTH - 1)

    @property
    def edit_x(self):
        return min(self.cursor_x, self.max_edit_x)

    @property
    def keyboard_note(self):
        return self._piano_keyboard.note

    @property
    def play_pos(self):
        play_info = self._play_info

        if not play_info.is_playing:
            return -1

        pos = int((time.time() - play_info.start_time) * 120 / play_info.speed)

        if play_info.is_looping:
            pos = pos % play_info.length
        elif pos >= play_info.length:
            pos = -1

        return pos

    def add_edit_history_before(self):
        self._history_data = data = {}
        data["sound"] = self._sound_picker.value
        data["cursor_before"] = (self.cursor_x, self.cursor_y)
        data["before"] = self.sound_data.copy()

    def add_edit_history_after(self):
        data = self._history_data
        data["cursor_after"] = (self.cursor_x, self.cursor_y)
        data["after"] = self.sound_data.copy()
        self.add_edit_history(self._history_data)

    def _play(self):
        sound = pyxel.sound(self._sound_picker.value)

        play_info = self._play_info
        play_info.is_playing = True
        play_info.is_looping = self._loop_button.value
        play_info.start_time = time.time()
        play_info.speed = sound.speed
        play_info.length = len(sound.note)

        self._play_button.is_enabled = False
        self._stop_button.is_enabled = True
        self._loop_button.is_enabled = False

        pyxel.play(0, self._sound_picker.value, loop=play_info.is_looping)

    def _stop(self):
        play_info = self._play_info
        play_info.is_playing = False

        self._play_button.is_enabled = True
        self._stop_button.is_enabled = False
        self._loop_button.is_enabled = True

        pyxel.stop(0)

    def __on_undo(self, data):
        self._sound_picker.value = data["sound"]
        self.cursor_x, self.cursor_y = data["cursor_before"]
        self.sound_data[:] = data["before"]

    def __on_redo(self, data):
        self._sound_picker.value = data["sound"]
        self.cursor_x, self.cursor_y = data["cursor_after"]
        self.sound_data[:] = data["after"]

    def __on_update(self):
        if pyxel.btnp(pyxel.KEY_SPACE):
            if self._play_info.is_playing:
                self._stop_button.press()
            else:
                self._play_button.press()

        if self._loop_button.is_enabled and pyxel.btnp(pyxel.KEY_L):
            self._loop_button.press()

        if self._play_info.is_playing and self.play_pos < 0:
            self._stop()

        if pyxel.btnp(pyxel.KEY_PAGE_UP):
            self.octave = min(self.octave + 1, 3)

        if pyxel.btnp(pyxel.KEY_PAGE_DOWN):
            self.octave = max(self.octave - 1, 0)

        if self._play_info.is_playing:
            return

        if self.cursor_x > 0 and pyxel.btnp(pyxel.KEY_LEFT, WIDGET_HOLD_TIME,
                                            WIDGET_REPEAT_TIME):
            self.cursor_x = self.edit_x - 1

        if self.cursor_x < self.max_edit_x and pyxel.btnp(
                pyxel.KEY_RIGHT, WIDGET_HOLD_TIME, WIDGET_REPEAT_TIME):
            self.cursor_x += 1

        if self.cursor_y > 0 and pyxel.btnp(pyxel.KEY_UP, WIDGET_HOLD_TIME,
                                            WIDGET_REPEAT_TIME):
            self.cursor_y -= 1

        if self.cursor_y < 3 and pyxel.btnp(pyxel.KEY_DOWN, WIDGET_HOLD_TIME,
                                            WIDGET_REPEAT_TIME):
            self.cursor_y += 1

    def __on_draw(self):
        self.draw_frame(11, 16, 218, 157)
        pyxel.text(23, 18, "SOUND", 6)
        pyxel.text(83, 18, "SPEED", 6)
        pyxel.text(17, 150, "TON", 6)
        pyxel.text(17, 158, "VOL", 6)
        pyxel.text(17, 166, "EFX", 6)

    def __on_sound_picker_change(self, value):
        sound = pyxel.sound(value)
        self._speed_picker.value = sound.speed

    def __on_speed_picker_change(self, value):
        sound = pyxel.sound(self._sound_picker.value)
        sound.speed = value

    def __on_play_button_press(self):
        self._play()

    def __on_stop_button_press(self):
        self._stop()

    def __on_play_button_mouse_hover(self, x, y):
        self.parent.help_message = "PLAY:SPACE"

    def __on_stop_button_mouse_hover(self, x, y):
        self.parent.help_message = "STOP:SPACE"

    def __on_loop_button_mouse_hover(self, x, y):
        self.parent.help_message = "LOOP:L"
Esempio n. 15
0
class App(Widget):
    def __init__(self, resource_file):
        resource_file = os.path.join(os.getcwd(), resource_file)
        root, ext = os.path.splitext(resource_file)
        if ext != pyxel.RESOURCE_FILE_EXTENSION:
            resource_file += pyxel.RESOURCE_FILE_EXTENSION

        pyxel.init(APP_WIDTH,
                   APP_HEIGHT,
                   caption="Pyxel Editor - {}".format(resource_file))
        pyxel.mouse(True)

        if os.path.exists(resource_file):
            pyxel.load(resource_file)

        if ext == ".pyxel":
            resource_file = root + pyxel.RESOURCE_FILE_EXTENSION

        super().__init__(None, 0, 0, pyxel.width, pyxel.height)

        self._resource_file = resource_file
        self._editor_list = [
            ImageEditor(self),
            TileMapEditor(self),
            SoundEditor(self),
            MusicEditor(self),
        ]
        self._editor_button = RadioButton(
            self,
            1,
            1,
            pyxel.IMAGE_BANK_FOR_SYSTEM,
            EDITOR_IMAGE_X,
            EDITOR_IMAGE_Y,
            4,
            0,
        )
        self._undo_button = ImageButton(
            self,
            48,
            1,
            pyxel.IMAGE_BANK_FOR_SYSTEM,
            EDITOR_IMAGE_X + 36,
            EDITOR_IMAGE_Y,
        )
        self._redo_button = ImageButton(
            self,
            57,
            1,
            pyxel.IMAGE_BANK_FOR_SYSTEM,
            EDITOR_IMAGE_X + 45,
            EDITOR_IMAGE_Y,
        )
        self._save_button = ImageButton(
            self,
            75,
            1,
            pyxel.IMAGE_BANK_FOR_SYSTEM,
            EDITOR_IMAGE_X + 54,
            EDITOR_IMAGE_Y,
        )
        self.help_message = ""

        self._editor_button.add_event_handler(
            "change", lambda value: self._set_editor(value))
        self.add_event_handler("update", self.__on_update)
        self.add_event_handler("draw", self.__on_draw)
        self._undo_button.add_event_handler("press",
                                            self.__on_undo_button_press)
        self._undo_button.add_event_handler("repeat",
                                            self.__on_undo_button_press)
        self._redo_button.add_event_handler("press",
                                            self.__on_redo_button_press)
        self._redo_button.add_event_handler("repeat",
                                            self.__on_redo_button_press)
        self._save_button.add_event_handler("press",
                                            self.__on_save_button_press)
        self._editor_button.add_event_handler(
            "mouse_hover", self.__on_editor_button_mouse_hover)
        self._undo_button.add_event_handler("mouse_hover",
                                            self.__on_undo_button_mouse_hover)
        self._redo_button.add_event_handler("mouse_hover",
                                            self.__on_redo_button_mouse_hover)
        self._save_button.add_event_handler("mouse_hover",
                                            self.__on_save_button_mouse_hover)

        image_file = os.path.join(os.path.dirname(__file__), "assets",
                                  EDITOR_IMAGE_NAME)
        pyxel.image(pyxel.IMAGE_BANK_FOR_SYSTEM,
                    system=True).load(EDITOR_IMAGE_X, EDITOR_IMAGE_Y,
                                      image_file)

        self._set_editor(0)

        pyxel.run(self.update_widgets, self.draw_widgets)

    def _set_editor(self, editor):
        self._editor_button.value = editor

        for i, widget in enumerate(self._editor_list):
            widget.is_visible = i == editor

    def __on_update(self):
        if pyxel._drop_file:
            ext = os.path.splitext(pyxel._drop_file)[1]

            if ext == pyxel.RESOURCE_FILE_EXTENSION:
                pyxel.stop()

                if pyxel.btn(pyxel.KEY_CONTROL):
                    editor = self._editor_list[self._editor_button.value]
                    editor.reset_history()

                    if isinstance(editor, ImageEditor):
                        pyxel.load(pyxel._drop_file,
                                   tilemap=False,
                                   sound=False,
                                   music=False)
                    elif isinstance(editor, TileMapEditor):
                        pyxel.load(pyxel._drop_file,
                                   image=False,
                                   sound=False,
                                   music=False)
                    elif isinstance(editor, SoundEditor):
                        pyxel.load(pyxel._drop_file,
                                   image=False,
                                   tilemap=False,
                                   music=False)
                    elif isinstance(editor, MusicEditor):
                        pyxel.load(pyxel._drop_file,
                                   image=False,
                                   tilemap=False,
                                   sound=False)
                else:
                    for editor in self._editor_list:
                        editor.reset_history()
                    pyxel.load(pyxel._drop_file)

                pyxel._caption(pyxel._drop_file)
            else:
                self._editor_list[
                    self._editor_button.value].call_event_handler(
                        "drop", pyxel._drop_file)

        if pyxel.btn(pyxel.KEY_LEFT_ALT) or pyxel.btn(pyxel.KEY_RIGHT_ALT):
            editor = self._editor_button.value
            editor_count = len(self._editor_list)

            if pyxel.btnp(pyxel.KEY_LEFT):
                self._set_editor((editor - 1) % editor_count)
            elif pyxel.btnp(pyxel.KEY_RIGHT):
                self._set_editor((editor + 1) % editor_count)

        editor = self._editor_list[self._editor_button.value]
        self._undo_button.is_enabled = editor.can_undo
        self._redo_button.is_enabled = editor.can_redo

        if pyxel.btn(pyxel.KEY_CONTROL):
            if pyxel.btnp(pyxel.KEY_S):
                self._save_button.press()

            if editor.can_undo and pyxel.btnp(pyxel.KEY_Z, WIDGET_HOLD_TIME,
                                              WIDGET_REPEAT_TIME):
                self._undo_button.press()

            if editor.can_redo and pyxel.btnp(pyxel.KEY_Y, WIDGET_HOLD_TIME,
                                              WIDGET_REPEAT_TIME):
                self._redo_button.press()

    def __on_draw(self):
        pyxel.cls(WIDGET_BACKGROUND_COLOR)
        pyxel.rect(0, 0, 240, 9, WIDGET_PANEL_COLOR)
        pyxel.line(0, 9, 239, 9, WIDGET_SHADOW_COLOR)

        pyxel.text(93, 2, self.help_message, 13)
        self.help_message = ""

    def __on_undo_button_press(self):
        self._editor_list[self._editor_button.value].undo()

    def __on_redo_button_press(self):
        self._editor_list[self._editor_button.value].redo()

    def __on_save_button_press(self):
        pyxel.save(self._resource_file)

    def __on_editor_button_mouse_hover(self, x, y):
        self.help_message = "EDITOR:ALT+LEFT/RIGHT"

    def __on_undo_button_mouse_hover(self, x, y):
        self.help_message = "UNDO:CTRL+Z"

    def __on_redo_button_mouse_hover(self, x, y):
        self.help_message = "REDO:CTRL+Y"

    def __on_save_button_mouse_hover(self, x, y):
        self.help_message = "SAVE:CTRL+S"