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)
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)
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)
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)
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)
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)
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)
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)
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"
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"
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)
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"
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)
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"
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"