diff --git a/Musicreater/builtin_plugins/to_commands/main.py b/Musicreater/builtin_plugins/to_commands/main.py index ac5b249..407cc1e 100644 --- a/Musicreater/builtin_plugins/to_commands/main.py +++ b/Musicreater/builtin_plugins/to_commands/main.py @@ -105,6 +105,10 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): license="Same as Musicreater", ) + + # 暂时没有适配动画内容和替换顺序 + # 金羿正在处理这个,不需要改 + # 但是返回值和接口内容不会变,直接用即可 @staticmethod def generate_progressbar( max_score: int, @@ -129,7 +133,7 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): ------- list[MineCommand,] """ - pgs_style = progressbar_style.base_style + orignal_style_string = progressbar_style.style_base_string """用于被替换的进度条原始样式""" """ @@ -143,19 +147,21 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): | `%%%` | 当前进度比率 | | `_` | 用以表示进度条占位| """ - per_value_in_each = max_score / pgs_style.count("_") + per_value_in_each = max_score / orignal_style_string.count("_") """每个进度条代表的分值""" result: List[MineCommand] = [] - if r"%^s" in pgs_style: - pgs_style = pgs_style.replace(r"%^s", str(max_score)) + if "%^s" in orignal_style_string: + orignal_style_string = orignal_style_string.replace("%^s", str(max_score)) - if r"%^t" in pgs_style: - pgs_style = pgs_style.replace(r"%^t", mctick2timestr(max_score)) + if "%^t" in orignal_style_string: + orignal_style_string = orignal_style_string.replace( + "%^t", mctick2timestr(max_score) + ) sbn_pc = scoreboard_name[:2] - if r"%%%" in pgs_style: + if "%%%" in orignal_style_string: result.append( MineCommand( 'scoreboard objectives add {}PercT dummy "百分比计算"'.format( @@ -192,7 +198,7 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): + "scoreboard players operation @s {} = @s {}".format( sbn_pc + "PercT", scoreboard_name ), - annotation="赋值临时百分比", + annotation="赋值当前进度", ) ) result.append( @@ -203,7 +209,7 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): + "scoreboard players operation @s {} *= n100 {}".format( sbn_pc + "PercT", scoreboard_name ), - annotation="转换临时百分比之单位至%(扩大精度)", + annotation="转换当前进度之单位至百分比(扩大精度)", ) ) result.append( @@ -214,11 +220,11 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): + "scoreboard players operation @s {} /= MaxScore {}".format( sbn_pc + "PercT", scoreboard_name ), - annotation="计算百分比", + annotation="计算进度百分比", ) ) - if r"%%t" in pgs_style: + if "%%t" in orignal_style_string: result.append( MineCommand( 'scoreboard objectives add {}TMinT dummy "时间计算:分"'.format( @@ -241,7 +247,7 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): "@a[scores={" + scoreboard_name + "=1..}]" ) + "scoreboard players set n20 {} 20".format(scoreboard_name), - annotation="设置常量20", + annotation="设置常量 20", ) ) result.append( @@ -250,7 +256,7 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): "@a[scores={" + scoreboard_name + "=1..}]" ) + "scoreboard players set n60 {} 60".format(scoreboard_name), - annotation="设置常量60", + annotation="设置常量 60", ) ) @@ -262,7 +268,7 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): + "scoreboard players operation @s {} = @s {}".format( sbn_pc + "TMinT", scoreboard_name ), - annotation="赋值临时分", + annotation="赋值临时分变量", ) ) result.append( @@ -273,7 +279,7 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): + "scoreboard players operation @s {} /= n20 {}".format( sbn_pc + "TMinT", scoreboard_name ), - annotation="转换临时分之单位为秒(缩减精度)", + annotation="转换临时分变量之单位为秒(缩减精度)", ) ) result.append( @@ -296,7 +302,7 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): + "scoreboard players operation @s {} /= n60 {}".format( sbn_pc + "TMinT", scoreboard_name ), - annotation="转换临时分之单位为分(缩减精度)", + annotation="转换临时分变量之单位为分(缩减精度)", ) ) @@ -312,54 +318,54 @@ class NoteDataConvert2CommandPlugin(LibraryPluginBase): ) ) - for i in range(pgs_style.count("_")): + for i in range(orignal_style_string.count("_")): npg_stl = ( - pgs_style.replace("_", progressbar_style.played_style, i + 1) - .replace("_", progressbar_style.to_play_style) - .replace(r"%%N", music_name) + orignal_style_string.replace("_", progressbar_style.progress_played, i + 1) + .replace("_", progressbar_style.progress_toplay) + .replace("%%N", music_name) .replace( - r"%%s", + "%%s", '"},{"score":{"name":"*","objective":"' + scoreboard_name + '"}},{"text":"', ) .replace( - r"%%%", - r'"},{"score":{"name":"*","objective":"' + "%%%", + '"},{"score":{"name":"*","objective":"' + sbn_pc - + r'PercT"}},{"text":"%', + + 'PercT"}},{"text":"%', ) .replace( - r"%%t", - r'"},{"score":{"name":"*","objective":"{-}TMinT"}},{"text":":"},' - r'{"score":{"name":"*","objective":"{-}TSecT"}},{"text":"'.replace( - r"{-}", sbn_pc + "%%t", + '"},{"score":{"name":"*","objective":"{-}TMinT"}},{"text":":"},' + '{"score":{"name":"*","objective":"{-}TSecT"}},{"text":"'.replace( + "{-}", sbn_pc ), ) ) result.append( MineCommand( execute_command_head.format( - r"@a[scores={" + "@a[scores={" + scoreboard_name + f"={int(i * per_value_in_each)}..{ceil((i + 1) * per_value_in_each)}" - + r"}]" + + "}]" ) - + r'titleraw @s actionbar {"rawtext":[{"text":"' + + 'titleraw @s actionbar {"rawtext":[{"text":"' + npg_stl - + r'"}]}', + + '"}]}', annotation="进度条显示", ) ) - if r"%%%" in pgs_style: + if "%%%" in orignal_style_string: result.append( MineCommand( "scoreboard objectives remove {}PercT".format(sbn_pc), annotation="移除临时百分比变量", ) ) - if r"%%t" in pgs_style: + if "%%t" in orignal_style_string: result.append( MineCommand( "scoreboard objectives remove {}TMinT".format(sbn_pc), diff --git a/Musicreater/builtin_plugins/to_commands/progressbar.py b/Musicreater/builtin_plugins/to_commands/progressbar.py index 757a846..09da8cc 100644 --- a/Musicreater/builtin_plugins/to_commands/progressbar.py +++ b/Musicreater/builtin_plugins/to_commands/progressbar.py @@ -26,23 +26,34 @@ from typing import BinaryIO, Optional, Dict, List, Callable, Tuple, Mapping class ProgressBarStyle: """进度条样式类""" - base_style: str + style_base_string: str """基础样式""" - to_play_style: str + progress_toplay: str """未播放之样式""" - played_style: str + progress_played: str """已播放之样式""" + is_animate_autoloop: bool + """所示动画是否循环""" + + animate_circle: Dict[str, Dict[int, str]] + """定义动画样式""" + def __init__( self, - base_s: Optional[str] = None, - to_play_s: Optional[str] = None, - played_s: Optional[str] = None, + base_string: str = "【%%N】%A%▶ %%s/%^s (%%t|%^t) \n" + "[§e_________________________§r] %%%", + to_play_style: str = "§7=", + played_style: str = "=", + animate_loop: bool = True, + animate_circle: Dict[str, Dict[int, str]] = { + "%A%": {5: "-", 10: "\\\\", 15: "|", 20: "/"} + }, ): """ - 用于存储进度条样式的类 + 用于存储进度条样式的类,标识符替换顺序如下表 | 标识符 | 指定的可变量 | |---------|----------------| @@ -53,14 +64,15 @@ class ProgressBarStyle: | `%^t` | 曲目总时长 | | `%%%` | 当前进度比率 | | `_` | 用以表示进度条占位| + | `%*%` | 指定*的动画内容 |a Parameters ------------ - base_s: str + base_string: str 基础样式,用以定义进度条整体 - to_play_s: str + to_play_style: str 进度条样式:尚未播放的样子 - played_s: str + played_style: str 已经播放的样子 Returns @@ -68,54 +80,32 @@ class ProgressBarStyle: ProgressBarStyle 类 """ - self.base_style = ( - base_s if base_s else r"▶ %%N [ %%s/%^s %%% §e__________§r %%t|%^t ]" - ) - self.to_play_style = to_play_s if to_play_s else r"§7=" - self.played_style = played_s if played_s else r"=" - - @classmethod - def from_tuple(cls, tuplized_style: Optional[Tuple[str, Tuple[str, str]]]): - """自旧版进度条元组表示法读入数据(已不建议使用)""" - - if tuplized_style is None: - return cls( - r"▶ %%N [ %%s/%^s %%% §e__________§r %%t|%^t ]", - r"§7=", - r"=", - ) - - if isinstance(tuplized_style, tuple): - if isinstance(tuplized_style[0], str) and isinstance( - tuplized_style[1], tuple - ): - if isinstance(tuplized_style[1][0], str) and isinstance( - tuplized_style[1][1], str - ): - return cls( - tuplized_style[0], tuplized_style[1][0], tuplized_style[1][1] - ) - raise ValueError( - "元组表示的进度条样式组 {} 格式错误,已不建议使用此功能,请尽快更换。".format( - tuplized_style - ) - ) + self.style_base_string = base_string + self.progress_toplay = to_play_style + self.progress_played = played_style + self.is_animate_autoloop = animate_loop + self.animate_circle = animate_circle def set_base_style(self, value: str): """设置基础样式""" - self.base_style = value + self.style_base_string = value def set_to_play_style(self, value: str): """设置未播放之样式""" - self.to_play_style = value + self.progress_toplay = value def set_played_style(self, value: str): """设置已播放之样式""" - self.played_style = value + self.progress_played = value def copy(self): - dst = ProgressBarStyle(self.base_style, self.to_play_style, self.played_style) - return dst + return ProgressBarStyle( + self.style_base_string, + self.progress_toplay, + self.progress_played, + self.is_animate_autoloop, + self.animate_circle, + ) def play_output( self, @@ -141,24 +131,37 @@ class ProgressBarStyle: 进度条字符串 """ - return ( - self.base_style.replace(r"%%N", music_name) - .replace(r"%%s", str(played_ticks)) - .replace(r"%^s", str(total_ticks)) - .replace(r"%%t", mctick2timestr(played_ticks)) - .replace(r"%^t", mctick2timestr(total_ticks)) + alpha_string = ( + self.style_base_string.replace("%%N", music_name) + .replace("%%s", str(played_ticks)) + .replace("%^s", str(total_ticks)) + .replace("%%t", mctick2timestr(played_ticks)) + .replace("%^t", mctick2timestr(total_ticks)) .replace( - r"%%%", + "%%%", "{:0>5.2f}%".format(int(10000 * played_ticks / total_ticks) / 100), ) .replace( "_", - self.played_style, - (played_ticks * self.base_style.count("_") // total_ticks) + 1, + self.progress_played, + (played_ticks * self.style_base_string.count("_") // total_ticks) + 1, ) - .replace("_", self.to_play_style) + .replace("_", self.progress_toplay) ) + for key, animate_dict in self.animate_circle.items(): + max_animate_tick = max(animate_dict.keys()) + if self.is_animate_autoloop: + animate_time_key = 0 + for time_key in animate_dict.keys(): + animate_time_key = time_key + if time_key > played_ticks % max_animate_tick: + break + else: + animate_time_key = max_animate_tick + alpha_string = alpha_string.replace(key, animate_dict[animate_time_key]) + return alpha_string + def mctick2timestr(mc_tick: int) -> str: """ @@ -167,11 +170,7 @@ def mctick2timestr(mc_tick: int) -> str: return "{:0>2d}:{:0>2d}".format(mc_tick // 1200, (mc_tick // 20) % 60) -DEFAULT_PROGRESSBAR_STYLE = ProgressBarStyle( - r"▶ %%N [ %%s/%^s %%% §e__________§r %%t|%^t ]", - r"§7=", - r"=", -) +DEFAULT_PROGRESSBAR_STYLE = ProgressBarStyle() """ 默认的进度条样式 """ diff --git a/Musicreater/builtin_plugins/to_commands/utils.py b/Musicreater/builtin_plugins/to_commands/utils.py index fadb242..88e4ed9 100644 --- a/Musicreater/builtin_plugins/to_commands/utils.py +++ b/Musicreater/builtin_plugins/to_commands/utils.py @@ -28,7 +28,7 @@ from typing import ( Literal, ) -from Musicreater import MineNote +from Musicreater import MineNote, SingleNote from Musicreater.constants import MM_INSTRUMENT_DEVIATION_TABLE @@ -44,15 +44,15 @@ def minenote_to_command_parameters( """ 将 MineNote 对象转为《我的世界》音符播放所需之参数 - Parameters - ------------ + 参数 + ---- mine_note: MineNote - 音符对象 + 我的世界音符对象 deviation: float 音调偏移量 - Returns - --------- + 返回 + ---- tuple[float, float, float], float, float 播放视角坐标, 指令音量参数, 指令音调参数 """ @@ -77,3 +77,39 @@ def minenote_to_command_parameters( ) ), ) + + +def calculate_minecraft_pitch( + note: MineNote, pitch_deviation: float = 0 +) -> Optional[float]: + """ + 计算音符的音调参数 + + 参数 + ---- + note: MineNote + 我的世界音符对象 + deviation: float + 音调偏移量 + + 返回 + ---- + Optional[float] + 音调参数, 当为打击乐器时为 None + """ + return ( + None + if note.percussive + else ( + 2 + ** ( + ( + note.pitch + - 60 + - MM_INSTRUMENT_DEVIATION_TABLE.get(note.instrument, 6) + + pitch_deviation + ) + / 12 + ) + ) + ) diff --git a/docs/编写插件.md b/docs/编写插件.md index 6182e55..4da9bd0 100644 --- a/docs/编写插件.md +++ b/docs/编写插件.md @@ -1,5 +1,5 @@ -# 示例插件:导入音符数据 +# 教程:编写插件 > 版权所有 © 2026 金羿 > Copyright © 2026 Eilles @@ -20,8 +20,8 @@ Email [TriM-Organization@hotmail.com](mailto:TriM-Organization@hotmail.com) ``` 本教程文档的关联文件是: - - 全曲导入、音轨导入插件示例:[exp_importdata_plugin.py](../examples/exp_importdata_plugin.py) - - 导出曲目、导出音轨插件示例:[exp_dataexport_plugin.py](../examples/exp_dataexport_plugin.py) +- 全曲导入、音轨导入插件示例:[exp_importdata_plugin.py](../examples/exp_importdata_plugin.py) +- 导出曲目、导出音轨插件示例:[exp_dataexport_plugin.py](../examples/exp_dataexport_plugin.py) ## 新建文件 @@ -159,7 +159,7 @@ class ...: | 支持库 | 无 | 无 | 无 | 无 | 无 | | 服务 | `serve` | `Callable[[Optional[PluginConfig]], None]` | 无 | 无 | 用于提供后台服务或一次性任务,由运行时调用(暂无设计思路,相关讨论请见[项目待办清单](../TO-DO.md#讨论)) | -也就是说,举个例子:一个**用于导入**的插件类必须包含一个 `loadbytes` 方法,用于从字节流中导入数据。可选是否单独实现 `load` 方法,如果不单独实现,则在调用时,会直接通过打开文件后传参数给 `loadbytes` 来实现。 +也就是说,举个例子:一个**用于导入**的插件类必须定义一个 `loadbytes` 方法,用于从字节流中导入数据。可选是否单独实现 `load` 方法,如果不单独实现,则已经继承的方法会在调用时,直接通过打开文件后传参数给 `loadbytes` 来实现。 ```python @... diff --git a/old-things/Musicreater/experiment.py b/old-things/Musicreater/experiment.py index 41bade6..8e4ca7d 100644 --- a/old-things/Musicreater/experiment.py +++ b/old-things/Musicreater/experiment.py @@ -501,7 +501,7 @@ class FutureMidiConvertJavaE(MidiConvert): ------- list[MineCommand,] """ - pgs_style = progressbar_style.base_style + pgs_style = progressbar_style.style_base_string """用于被替换的进度条原始样式""" """ @@ -686,8 +686,8 @@ class FutureMidiConvertJavaE(MidiConvert): for i in range(pgs_style.count("_")): npg_stl = ( - pgs_style.replace("_", progressbar_style.played_style, i + 1) - .replace("_", progressbar_style.to_play_style) + pgs_style.replace("_", progressbar_style.progress_played, i + 1) + .replace("_", progressbar_style.progress_toplay) .replace(r"%%N", self.music_name) .replace( r"%%s", diff --git a/old-things/Musicreater/old_main.py b/old-things/Musicreater/old_main.py index 32cd852..a536b3e 100644 --- a/old-things/Musicreater/old_main.py +++ b/old-things/Musicreater/old_main.py @@ -1308,7 +1308,7 @@ class MidiConvert(MusicSequence): ------- list[MineCommand,] """ - pgs_style = progressbar_style.base_style + pgs_style = progressbar_style.style_base_string """用于被替换的进度条原始样式""" """ @@ -1493,8 +1493,8 @@ class MidiConvert(MusicSequence): for i in range(pgs_style.count("_")): npg_stl = ( - pgs_style.replace("_", progressbar_style.played_style, i + 1) - .replace("_", progressbar_style.to_play_style) + pgs_style.replace("_", progressbar_style.progress_played, i + 1) + .replace("_", progressbar_style.progress_toplay) .replace(r"%%N", self.music_name) .replace( r"%%s",