203 Commits

Author SHA1 Message Date
bgArray
ab3c55e7b7 2023/1/5 update-窗口5
这个链接-槽好抽象,明天再研究了
2023-01-05 23:02:15 +08:00
bgArray
082934d918 2023/1/4 update-窗口4
开始自己写喽
2023-01-04 22:44:00 +08:00
bgArray
28d59f8be9 2023/1/3 update-窗口3
还有很多要改的,得加油
2023-01-03 21:55:08 +08:00
bgArray
1103a06897 !2 同步-2023/1/2
Merge pull request !2 from bgArray/pkgver
2023-01-02 09:25:11 +00:00
bgArray
63499732eb 2023/1/2 update-新手答疑指南.md 2023-01-02 16:40:17 +08:00
EillesWan
be40f8f920 改错版本号了qwq 2023-01-02 14:32:25 +08:00
EillesWan
190ef70fc4 忘了改版本号 2023-01-02 14:31:23 +08:00
EillesWan
a74fd4b4de 更加优秀的打击乐器判断! 2023-01-02 14:28:25 +08:00
EillesWan
2ebdf6be24 修改版权声明以及部分教程文档 2023-01-01 03:23:48 +08:00
EillesWan
9ca0788eb2 准备修改协议 2022-12-31 13:21:30 +08:00
EillesWan
fba83ef968 Merge branch 'pkgver' of https://gitee.com/EillesWan/Musicreater into pkgver 2022-12-31 13:20:32 +08:00
EillesWan
68e019412d 没写完,但是新算法 2022-12-31 13:20:30 +08:00
bgArray
9734bf493a 窗口2 2022-12-30 17:06:34 +08:00
bgArray
bde2b4e378 update msctPkgver/main.py.
Signed-off-by: bgArray <474037765@qq.com>
2022-12-29 11:52:10 +00:00
bgArray
dc1efc9e84 窗口1 2022-12-29 17:47:22 +08:00
bgArray
b04c01772f 更新指令格式 2022-12-29 11:09:30 +08:00
EillesWan
88d36f94f0 Merge branch 'pkgver' of https://gitee.com/EillesWan/Musicreater into pkgver 2022-11-27 18:13:05 +08:00
EillesWan
8eda5c4736 别急,没写完 2022-11-27 18:13:01 +08:00
Eilles Wan
37ccbe3dae 没翻译完,差不多就行
没翻译完

Signed-off-by: Eilles Wan <w-yi_doctoryi@outlook.com>
2022-11-25 04:40:51 +00:00
EillesWan
be43e4a92a 修复mcpack制作过程中的问题 2022-11-20 15:28:09 +08:00
EillesWan
5929ae417d 改太快了,出问题了,修复了 2022-11-20 12:26:28 +08:00
EillesWan
517c7db112 好玩~ 2022-11-20 12:16:59 +08:00
EillesWan
3ae456c4d1 Merge branch 'pkgver' of https://gitee.com/EillesWan/Musicreater into pkgver 2022-11-20 12:02:45 +08:00
EillesWan
b0af5f4950 紧急修复文件路径问题和进度条问题(没修进度条,但是胜似修了) 2022-11-20 12:02:40 +08:00
Eilles Wan
1ccaa8e9aa update docs/功能使用说明.md.
Signed-off-by: Eilles Wan <w-yi_doctoryi@outlook.com>
2022-11-20 02:59:00 +00:00
EillesWan
75fabf9c37 行了,重要的不急 2022-10-30 01:58:29 +08:00
EillesWan
95e34f5c7b 不好意思,我急了 2022-10-30 01:40:53 +08:00
EillesWan
5bb0227a7a 没写完,不急 2022-10-30 01:39:20 +08:00
EillesWan
9c9ebe0a08 Bug++ 2022-10-23 02:12:11 +08:00
EillesWan
0b3a19faad 更新安卓端的使用方法说明 2022-10-16 23:16:46 +08:00
EillesWan
6cde168bf3 学校的更改 2022-10-16 21:19:14 +08:00
Eilles Wan
451d1d8e80 update msctPkgver/main.py.
插值OK

Signed-off-by: Eilles Wan <w-yi_doctoryi@outlook.com>
2022-10-07 12:23:02 +00:00
EillesWan
085ab3f4c0 没写完 2022-10-07 19:25:28 +08:00
EillesWan
a16109f29a 搞错了再来一发 2022-10-07 16:52:17 +08:00
EillesWan
813186bef9 快好了,不急不急 2022-10-07 16:49:47 +08:00
EillesWan
3921190832 okk准备睡觉 2022-10-06 00:06:41 +08:00
EillesWan
c32b94592a 更新文档及其翻译……,另外对无法批量转换带进度条的bug做了更正……现在批量可以用进度条了 2022-10-05 23:59:06 +08:00
EillesWan
77b7344277 把教程改了个名 2022-10-05 22:29:07 +08:00
EillesWan
0a17f8b8f8 Merge branch 'pkgver' of https://gitee.com/EillesWan/Musicreater into pkgver 2022-10-05 22:27:55 +08:00
EillesWan
f8d707ac11 由于Merge错误,我得提交未完成的修改 2022-10-05 22:21:13 +08:00
EillesWan
ad7e047abc Merge branch 'pkgver' of https://gitee.com/EillesWan/Musicreater into pkgver 2022-10-05 22:18:15 +08:00
EillesWan
5ea47c54cb 这是学校里做的更新 2022-10-05 22:18:03 +08:00
bgArray
b20f350da4 update README.md.
Signed-off-by: bgArray <474037765@qq.com>
2022-09-10 12:58:14 +00:00
Eilles
5aaae83020 呼呼,教程写完啦 2022-09-10 00:02:55 +08:00
Eilles
85e6340570 教程写完了,欧耶 2022-09-10 00:00:58 +08:00
Eilles
662c6506d8 Merge branch 'pkgver' of https://gitee.com/EillesWan/Musicreater into pkgver 2022-09-09 22:58:59 +08:00
Eilles
ad2fcd6f14 更新demo的输入操作,一并增加教程 2022-09-09 22:58:05 +08:00
bgArray
5dde31d081 帮金羿提交,顺便改点小语法 2022-09-09 14:14:51 +08:00
bgArray
2e11a9949b 格式化 2022-09-08 22:36:01 +08:00
EillesWan
3b53846ade ok 2022-08-09 15:13:25 +08:00
EillesWan
96af5183ac 库版 0.0.1 正式推出 2022-08-09 15:10:52 +08:00
bgArray
59fd2645e4 update README.md. 2022-08-08 16:07:19 +00:00
bgArray
33ce7ed8c8 update README.md. 2022-08-08 15:57:07 +00:00
bgArray
14f7d6fd7e update README.md. 2022-08-08 15:52:01 +00:00
bgArray
fb2fd13b21 readme 更新 2022-08-08 23:49:22 +08:00
EillesWan
5025cba356 魔法计划启动! 2022-08-08 22:08:08 +08:00
EillesWan
abb53a7499 没改 2022-07-22 17:06:09 +08:00
EillesWan
73854be7be 格式化一下文档 2022-07-12 11:48:32 +08:00
EillesWan
6f6a77d0b4 Merge branch 'pkgver' of https://gitee.com/EillesWan/Musicreater into pkgver 2022-07-12 11:46:49 +08:00
EillesWan
e0a3399fed 新增更新工具 2022-07-12 11:46:37 +08:00
CaryXiong
2afd6beb3f 更新 2022-06-30 12:14:22 +08:00
bgArray
9517c49ec5 修正库导入BUG 2022-06-28 07:43:15 +08:00
bgArray
887452184b update msctPkgver/load_InstrumentLabel.py. 2022-06-26 12:06:52 +00:00
Eilles Wan
d36134e525 诸葛八卦没改完
我来给他改一下,改完来,这家伙没料到我后面留了一手吧,qwq
2022-06-25 16:17:42 +00:00
bgArray
453ca745af 修改算法,修正bug 2022-06-25 23:20:56 +08:00
EillesWan
7d814bcda2 !!update 2022-06-25 22:21:12 +08:00
CaryXiong
55b933ac85 更新算法,使之适配多乐器 2022-06-24 13:46:46 +08:00
EillesWan
56fb029e75 新增批量转换新样例 2022-06-19 02:04:17 +08:00
EillesWan
c5a7dfb608 小改动 2022-06-19 01:39:50 +08:00
EillesWan
0a640267ff 修复进度条显示错误 2022-06-19 01:36:52 +08:00
EillesWan
a6d7022f87 修复错误 2022-06-19 01:26:53 +08:00
EillesWan
dcc62ca66d 完成延时播放器 2022-06-19 01:07:07 +08:00
EillesWan
992572cbf1 更新了一下文件结构 2022-06-08 01:50:14 +08:00
EillesWan
ce1099a246 我再更新一些小东西 2022-06-07 23:49:04 +08:00
EillesWan
2340741bb9 更新便于使用的预览程序 2022-06-07 23:43:14 +08:00
EillesWan
3f0f714a7c Merge branch 'pkgver' of https://gitee.com/EillesWan/Musicreater into pkgver 2022-05-16 16:02:48 +08:00
EillesWan
65c23ca427 没问题 2022-05-16 16:02:43 +08:00
bgArray
3b6cb3865f 教程 2022-05-11 23:38:26 +08:00
EillesWan
cae0b7f23d 有bug 2022-05-08 18:33:28 +08:00
EillesWan
e1d4cd9933 更新自动重置积分、进度条的功能 2022-05-08 01:30:30 +08:00
EillesWan
3499c05eb4 修复x轴不增加的bug 2022-04-29 23:17:14 +08:00
EillesWan
259fb04980 完成了更改,现在支持bdx导出 2022-04-29 18:45:06 +08:00
EillesWan
8ce7a9fa83 update format 2022-04-29 11:34:41 +08:00
EillesWan
affb5b5404 Merge branch 'pkgver' of https://gitee.com/EillesWan/Musicreater into pkgver 2022-04-29 11:33:52 +08:00
EillesWan
1805ab53c0 新增bdx转换功能 2022-04-29 11:29:49 +08:00
bgArray
eda3a957cf 修复已知问题 2022-04-12 18:11:57 +08:00
bgArray
4788d8949b 格式化 2022-04-12 14:15:33 +08:00
EillesWan
8f6cc04780 重设样例代码 2022-04-07 08:27:43 +08:00
EillesWan
6cb5c9ba89 提交包模式的更新 2022-04-05 23:43:03 +08:00
EillesWan
ae83f9c21e 更新了内部数据格式文档,修复部分bug 2022-04-05 00:55:43 +08:00
EillesWan
dd34ac9998 紧急更新,修复了无法将整首歌转换bdx的bug,其余bug正在发现。 2022-04-03 21:38:17 +08:00
EillesWan
2da06136c5 Merge branch 'master' of https://gitee.com/EillesWan/Musicreater 2022-04-03 00:51:39 +08:00
EillesWan
e9f4230a2d 金羿生日快乐~ 2022-04-03 00:51:34 +08:00
bgArray
1b7ab73c02 update README_EN.md. 2022-04-01 07:54:34 +00:00
EillesWan
2624c081bb 生活不易,改README出气 2022-04-01 15:09:03 +08:00
EillesWan
87cc189da8 修正单词拼写错误 2022-04-01 15:07:22 +08:00
Eilles Wan
668bf480b2 重命名 README_en.md 为 README_EN.md 2022-04-01 06:42:30 +00:00
EillesWan
4cc3f2678f 没事?没事就改README! 2022-04-01 14:38:50 +08:00
EillesWan
701e9d5129 Merge branch 'master' of https://gitee.com/EillesWan/Musicreater 2022-04-01 14:23:08 +08:00
EillesWan
8dd2694e82 左改改右改改,就是不改代码/qwq 2022-04-01 14:23:03 +08:00
bgArray
ac962f0ab7 update README.md. 2022-04-01 05:50:48 +00:00
EillesWan
b800384547 Merge branch 'master' of https://gitee.com/EillesWan/Musicreater 2022-04-01 12:48:41 +08:00
EillesWan
5da1041664 喵喵喵? 2022-04-01 12:48:35 +08:00
Eilles Wan
966ce515c3 update README.md. 2022-04-01 04:22:57 +00:00
EillesWan
349c255f5f LOGO 2022-04-01 11:53:43 +08:00
bgArray
cbb77086d0 update README.md. 2022-04-01 03:17:14 +00:00
bgArray
280e50f4cb update README.md. 2022-04-01 02:55:58 +00:00
bgArray
a2a37be8ef update README.md. 2022-04-01 02:33:10 +00:00
Eilles Wan
7acd6b7e38 update resources/myWords.txt. 移除上一次更改 2022-03-31 01:23:11 +00:00
bgArray
4c95f76cf9 update 道法重大更新 2022-03-30 03:01:08 +00:00
Eilles Wan
8a1a159eb8 update README.md. 2022-03-29 08:51:53 +00:00
Eilles Wan
cb43caef26 update README.md. 2022-03-29 08:51:29 +00:00
Eilles Wan
200167ef84 update README.md. 2022-03-29 08:51:23 +00:00
EillesWan
7e0a127406 Merge branch 'master' of https://gitee.com/EillesWan/Musicreater 2022-03-29 16:46:40 +08:00
EillesWan
5e70dd73a1 重大更新,我新增了很多名言名句!!! 2022-03-29 16:46:31 +08:00
bgArray
7229b12e99 删除文件 languages/log 2022-03-28 15:13:37 +00:00
bgArray
074124bc3d 删除文件 .idea 2022-03-28 15:13:09 +00:00
bgArray
91446bfd81 翻译保存器 2022-03-28 23:12:24 +08:00
EillesWan
5011efcdee Merge branch 'master' of https://gitee.com/EillesWan/Musicreater 2022-03-28 20:42:12 +08:00
EillesWan
3b4af19379 暂存更改以便pull 2022-03-28 20:40:17 +08:00
EillesWan
d3d89d2567 增强对于Linux的支持 2022-03-28 20:29:36 +08:00
EillesWan
441d1e9982 我把旧的MMFM的日志一起加入进来,作为历史的参考。 2022-03-28 14:04:30 +08:00
EillesWan
77e738cb7e 修改读我档 2022-03-28 12:33:35 +08:00
EillesWan
46b6884e64 Merge branch 'master' of https://gitee.com/EillesWan/Musicreater 2022-03-26 21:01:29 +08:00
EillesWan
d0a63d0f8e 为了pull,暂存更改 2022-03-26 21:01:23 +08:00
bgArray
887394570b update README.md. 2022-03-26 12:17:08 +00:00
EillesWan
c62806d470 更新安装指示,完成关于界面的编写,UI进一步制作中 2022-03-26 12:24:00 +08:00
EillesWan
d21c26d632 浅浅更新一下~ 2022-03-26 00:30:12 +08:00
EillesWan
26ec42a71d 慢慢更新。 2022-03-24 01:01:45 +08:00
EillesWan
245e2fa1ec 新增自动安装器 2022-03-21 19:05:27 +08:00
bgArray
e70fc806be update README_en.md. 2022-03-20 03:28:59 +00:00
bgArray
72a3715722 update README.md. 2022-03-20 03:27:06 +00:00
bgArray
fd3d27d596 update README.md. 2022-03-20 03:26:47 +00:00
bgArray
3d283bfded 编辑器 2022-03-20 11:20:59 +08:00
EillesWan
7d9b63b9fe 加flag 2022-03-19 19:59:16 +08:00
EillesWan
82850a3d74 终于……我知道Text组件怎么用了 2022-03-19 11:58:28 +08:00
EillesWan
629cfa402b 语言支持增加 2022-03-17 16:21:17 +08:00
EillesWan
0818957f51 新增语言支持 2022-03-16 16:21:10 +08:00
EillesWan
954a30f722 简单修改国际化支持 2022-03-13 22:29:57 +08:00
EillesWan
96e6bc2f7a update LISENCE and some words 2022-03-13 15:16:23 +08:00
bgArray
ca0e56e771 update LICENSE. 2022-03-12 10:24:56 +00:00
EillesWan
8fe71dbe0d 重新设计UI,准备进行国际化支持 2022-03-11 23:27:48 +08:00
EillesWan
97f334789e 改改改 2022-03-11 00:13:01 +08:00
EillesWan
d2a6ce2529 完全想好了窗口改怎么做了,正在逐步更新,顺便取代前尘旧物。 2022-03-10 21:42:11 +08:00
EillesWan
066e0b0cac Merge branch 'master' of https://gitee.com/EillesWan/Musicreater 2022-03-09 22:11:01 +08:00
EillesWan
052142ac08 正在修改,没改完 2022-03-09 22:10:54 +08:00
EillesWan
59c481f6da Merge branch 'master' of https://gitee.com/EillesWan/Musicreater 2022-03-06 23:49:23 +08:00
EillesWan
53c17f0328 没有做任何更改,上传一下做备份。 2022-03-06 23:46:35 +08:00
EillesWan
ed28fc4866 没有做任何更改,上传一下做备份。 2022-03-06 23:40:31 +08:00
EillesWan
320114533d 思想确认,具体请看群内,正在进一步修改UI,以及插件效果。 2022-02-07 18:51:51 +08:00
EillesWan
aa210ac678 代码重构第一步 2022-02-06 18:59:45 +08:00
EillesWan
c4dd7b1ce8 代码正在被重构,请不要更新功能,如果要更新,请推送至OldUI分支 2022-02-02 22:51:26 +08:00
EillesWan
99509be48c 慢慢改bug 2022-02-02 15:09:11 +08:00
EillesWan
073ae827ab Merge branch 'master' of https://gitee.com/EillesWan/Musicreater 2022-02-01 21:41:48 +08:00
EillesWan
58b312554d 改动 2022-02-01 21:36:52 +08:00
bgArray
55eeddb108 改bug 2022-02-01 21:35:46 +08:00
EillesWan
9d4a75cd41 先画个饼 2022-02-01 19:12:00 +08:00
EillesWan
882ce96b90 修复了部分midi文件无法读取的错误 2022-02-01 18:20:14 +08:00
bgArray
9093a66639 重传 2022-02-01 14:34:56 +08:00
bgArray
b48a66115a 删除文件 bgArrayLib/resourcesPath.rpposi 2022-02-01 06:32:40 +00:00
bgArray
db20a87ae9 删除文件 logs 2022-02-01 06:32:27 +00:00
bgArray
69eebd25a9 删除文件 log 2022-02-01 06:32:19 +00:00
bgArray
89ef3bcb55 修了一些BUG,但是有些BUG还没有解决 2022-02-01 14:31:44 +08:00
EillesWan
f08a2ff9be 修复了生成指令出错的问题 2022-02-01 01:46:38 +08:00
bgArray
9f8694ef14 新年第一次更新 2022-02-01 00:07:22 +08:00
EillesWan
81272a1166 紧急修改一下刚刚更新造成的bug 2022-01-31 23:07:22 +08:00
EillesWan
a83052bd5d 新增整个音乐生成单个BDX,同时需要合并一下诸葛亮的分支 2022-01-31 23:01:11 +08:00
EillesWan
2fcfdca0a0 修复部分bug,增加部分bug 2022-01-31 13:53:38 +08:00
bgArray
bcaeb129a5 删除文件 .idea 2022-01-30 08:11:02 +00:00
bgArray
36b639f029 ReadMe(en)更新 2022-01-30 16:06:51 +08:00
bgArray
4b241dfc0b 合并 2022-01-29 22:02:42 +08:00
bgArray
255cc84ef3 删除文件 .idea 2022-01-29 08:42:15 +00:00
bgArray
c04b622297 文件函数变更,新功能回增 2022-01-29 16:41:33 +08:00
bgArray
b6a63a794e 删除文件 log 2022-01-28 10:30:35 +00:00
bgArray
7c0dd218b2 删除文件 .idea 2022-01-28 10:30:29 +00:00
bgArray
19bbb92cff 小改动、回档 2022-01-28 18:29:51 +08:00
bgArray
26ee16f071 删除文件 log 2022-01-28 09:40:50 +00:00
bgArray
05eb0c05ec 删除文件 .idea 2022-01-28 09:32:54 +00:00
bgArray
5d2e0582c3 回档奥 2022-01-28 17:28:52 +08:00
bgArray
d3e0f78d2c 基础版本-δ-0.1.0,本地0.5.1 2022-01-28 17:07:29 +08:00
EillesWan
79a2dfb5b1 删掉一些没用的东西,此外用python38编译一遍……然后把 言·论 部分增加了一些……对了!言·论 指的是中间那行很富有哲理的话哦! 2022-01-28 00:48:28 +08:00
EillesWan
bf3367c7e4 Merge branch 'master' of https://gitee.com/EillesWan/Musicreater 2022-01-28 00:43:56 +08:00
EillesWan
c91f5cf2f9 更新 言·论 板块内容。 2022-01-28 00:43:10 +08:00
bgArray
d8ea747ef1 还不能用的新版本 2022-01-27 21:21:25 +08:00
EillesWan
39148a6c76 更新一下我的言论部分 2022-01-25 15:08:38 +08:00
EillesWan
0e3eb394ab 没有任何更改 2022-01-23 22:33:41 +08:00
EillesWan
f0dedabe1a Merge https://gitee.com/EillesWan/Musicreater 2022-01-23 22:02:36 +08:00
EillesWan
dda78ab35f 我也不知道改了什么,理论上什么都没改 2022-01-23 21:56:48 +08:00
Eilles Wan
5b6ff5ee68 none 2022-01-19 22:25:16 +08:00
bgArray
fcb1a25227 修bug 2022-01-19 18:03:52 +08:00
bgArray
81eb8e5376 日志和bug修改 2022-01-19 17:48:47 +08:00
bgArray
7e13b22d46 除个别外语法错误整体修正 2022-01-19 13:32:53 +08:00
EillesWan
07e153f215 感谢,bgArray “诸葛亮与八卦阵”的更改,此外,修了一些东东吧。 2022-01-19 12:31:37 +08:00
bgArray
908f622433 initial commit 2022-01-19 10:46:20 +08:00
EillesWan
5f7ca0859f 更新读我文档 2022-01-15 00:49:15 +08:00
EillesWan
32ae868c34 增强多语言支持 2022-01-15 00:40:17 +08:00
EillesWan
ce441e4905 更改一些东西 2022-01-14 22:49:21 +08:00
Eilles Wan
3dc099af7e 新增英语支持 2022-01-05 22:24:38 +08:00
Eilles Wan
cf7e51595e 新增多语言支持。 2022-01-03 20:45:25 +08:00
EillesWan
737b2d5f07 增加一个文件,等会再处理,先去上课了,作业一个字都没写 2022-01-03 14:55:35 +08:00
EillesWan
143de0bb37 把所有需要翻译的字符串用双引号字符串表示,其余全是单引号字符串 2022-01-03 14:50:14 +08:00
EillesWan
17f9fa7ffc 1.重新采用Tk作为窗口库
2.优化界面布局
3.修改部分按钮无响应的bug
4.新增启动时的Saying
5.删除命令行模式
6.更新README文件,并增添英文README
2022-01-02 21:43:34 +08:00
EillesWan
1bc1c6485b 新增滑块 2022-01-01 20:19:41 +08:00
75 changed files with 5663 additions and 4827 deletions

172
.gitignore vendored
View File

@@ -1,38 +1,20 @@
# Byte-compiled / optimized / DLL files
# sth. can't open
/msctPkgver/secrets/*.py
/msctPkgver/secrets/*.c
# mystuff
/.vscode
*.mid
*.midi
# Byte-compiled / optimized
__pycache__/
*.py[cod]
*.pyc
*$py.class
# OSX useful to ignore
*.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
@@ -44,23 +26,123 @@ lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# IntelliJ Idea family of suites
.idea
*.iml
## File-based project format:
*.ipr
*.iws
## mpeltonen/sbt-idea plugin
.idea_modules/
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Briefcase build directories
iOS/
macOS/
windows/
android/
linux/
django/
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# Pycharm
/.idea

88
1.py Normal file
View File

@@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file '1.ui'
##
## Created by: Qt User Interface Compiler version 6.4.1
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QMainWindow, QMenuBar, QSizePolicy,
QStatusBar, QTabWidget, QToolButton, QVBoxLayout,
QWidget)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.verticalLayoutWidget_2 = QWidget(self.centralwidget)
self.verticalLayoutWidget_2.setObjectName(u"verticalLayoutWidget_2")
self.verticalLayoutWidget_2.setGeometry(QRect(0, 0, 861, 681))
self.verticalLayout_2 = QVBoxLayout(self.verticalLayoutWidget_2)
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.tabWidget = QTabWidget(self.verticalLayoutWidget_2)
self.tabWidget.setObjectName(u"tabWidget")
self.tab = QWidget()
self.tab.setObjectName(u"tab")
self.toolButton_2 = QToolButton(self.tab)
self.toolButton_2.setObjectName(u"toolButton_2")
self.toolButton_2.setGeometry(QRect(30, 10, 24, 22))
self.tabWidget.addTab(self.tab, "")
self.tab_2 = QWidget()
self.tab_2.setObjectName(u"tab_2")
self.tabWidget.addTab(self.tab_2, "")
self.verticalLayout_2.addWidget(self.tabWidget)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(0, 0, 800, 26))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QStatusBar(MainWindow)
self.statusbar.setObjectName(u"statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.toolButton_2.clicked.connect(self.toolButton_2.click)
self.tabWidget.setCurrentIndex(0)
QMetaObject.connectSlotsByName(MainWindow)
# setupUi
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
self.toolButton_2.setText(QCoreApplication.translate("MainWindow", u"...", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab),
QCoreApplication.translate("MainWindow", u"Tab 1", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2),
QCoreApplication.translate("MainWindow", u"Tab 2", None))
# retranslateUi
if __name__ == "__main__":
import sys
from PySide6 import QtWidgets
app = QtWidgets.QApplication(sys.argv) # 创建一个QApplication也就是你要开发的软件app
MainWindow = QtWidgets.QMainWindow() # 创建一个QMainWindow用来装载你需要的各种组件、控件
# MainWindow = QtWidgets.QWidget() # 创建一个QMainWindow用来装载你需要的各种组件、控件
ui = Ui_MainWindow() # ui是你创建的ui类的实例化对象
ui.setupUi(MainWindow) # 执行类中的setupUi方法方法的参数是第二步中创建的QMainWindow
MainWindow.show() # 执行QMainWindow的show()方法显示这个QMainWindow
sys.exit(app.exec_()) # 使用exit()或者点击关闭按钮退出QApplication

91
1.ui Normal file
View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QWidget" name="verticalLayoutWidget_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>861</width>
<height>681</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Tab 1</string>
</attribute>
<widget class="QToolButton" name="toolButton_2">
<property name="geometry">
<rect>
<x>30</x>
<y>10</y>
<width>24</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Tab 2</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>26</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections>
<connection>
<sender>toolButton_2</sender>
<signal>clicked()</signal>
<receiver>toolButton_2</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>44</x>
<y>76</y>
</hint>
<hint type="destinationlabel">
<x>46</x>
<y>71</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -1,201 +1,219 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
**注意,以下条款或版权声明应当且必须是高于此项目中任何其他声明的**
1. 音·创的全部开发者享有其完整版权,其开发者可以在任一时刻终止以后音·创源代码开放,若经由其开发者授予特殊权利,则授权对象可以将源代码进行特定的被特殊授权的操作
2. 音·创或(及)其代码允许在 Apache2.0 协议的条款与说明下进行非商业使用
3. 除部分代码特殊声明外,音·创允许对其或(及)其代码进行商业化使用,但是需要经过音·创主要开发者(诸葛亮与八卦阵、金羿)的一致授权,同时,授权对象在商业化授权的使用过程中必须依照 Apache2.0 协议的条款与说明
4. 若存在对于音·创包含的部分代码的特殊开源声明,则此部分代码依照其特定的开源方式授权,但若此部分代码经由此部分代码的主要开发者一致特殊授权后商用,则授权对象在商用时依照此部分的开发者所准许的方式(或条款)进行商用,或默认依照 Apache2.0 协议进行商业化使用
5. Apache2.0 协议的英文原文副本可见下文
> The English Translation of the TERMS AND CONDITIONS above is listed below
>
> This translated version is for reference only and has no legal effect.
>
> The version with legal effect is the Chinese version above.
**Note, The TERMS AND CONDITIONS below should and must be above all others in this project**
1. *Musicreater* is fully copyrighted by all its developers, the developers have the right to make *Musicreater* close sourced at any time. Operations are permitted under specific terms instructed by its developer(s).
2. Non-commercial use of *Musicreater* and(or) its source code is permitted under Apache License 2.0.
3. Commercial use of *Musicreater* is permitted under Apache License 2.0 with the unanimous permission of the steering developers of *Musicreater* (*bgArray*诸葛亮与八卦阵 and *Eilles*金羿).
4. *Musicreater* is open sourced under priority given:
1. License granted by the core developer(s) of a section after negotiation.
2. Explicitly stated license.
3. Apache 2.0 License.
5. A copy of the original Apache Lisence 2.0 can be found below.
```text
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2022 Team-Ryoun 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray")
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```

532
PySide6-Pkg.ui Normal file
View File

@@ -0,0 +1,532 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>951</width>
<height>611</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTabWidget" name="tabO">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Tab 1</string>
</attribute>
<widget class="QWidget" name="verticalLayoutWidget_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>881</width>
<height>591</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTableWidget" name="tableWidget"/>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Tab 2</string>
</attribute>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>71</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
<widget class="QWidget" name="widget" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>30</y>
<width>281</width>
<height>131</height>
</rect>
</property>
<widget class="QWidget" name="verticalLayoutWidget_3">
<property name="geometry">
<rect>
<x>10</x>
<y>0</y>
<width>271</width>
<height>131</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="widget_2" native="true">
<property name="geometry">
<rect>
<x>280</x>
<y>30</y>
<width>281</width>
<height>131</height>
</rect>
</property>
<widget class="QWidget" name="verticalLayoutWidget_4">
<property name="geometry">
<rect>
<x>10</x>
<y>0</y>
<width>271</width>
<height>131</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="widget_3" native="true">
<property name="geometry">
<rect>
<x>10</x>
<y>160</y>
<width>781</width>
<height>191</height>
</rect>
</property>
<widget class="QWidget" name="verticalLayoutWidget_5">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>781</width>
<height>191</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_14">
<property name="text">
<string>默认保存路径:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox"/>
</item>
<item>
<widget class="QToolButton" name="toolButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_15">
<property name="text">
<string>速度倍率</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_17">
<property name="text">
<string>音量倍率</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QLabel" name="label_21">
<property name="text">
<string>最大指令生成高度</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_16">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<widget class="QLabel" name="label_24">
<property name="text">
<string>选择器模式</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_3"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label_18">
<property name="text">
<string>计分板名称</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="textEdit">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>22</height>
</size>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_20">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>22</height>
</size>
</property>
<property name="text">
<string>玩家选择器</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="textEdit_2">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>22</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="label_19">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>22</height>
</size>
</property>
<property name="text">
<string>bdx作者名称</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="textEdit">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>22</height>
</size>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QCheckBox" name="checkBox_2">
<property name="text">
<string>是否启用进度条</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>是否自定义进度条</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_22">
<property name="text">
<string>自定义进度条内容:</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="textEdit_3">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>22</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_18"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLabel" name="label_23">
<property name="maximumSize">
<size>
<width>120</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>选择命令格式版本</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_2">
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QLabel" name="label_25">
<property name="text">
<string>选择转换算法版本</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_4"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QLabel" name="label_26">
<property name="text">
<string>选择导出模式</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_5"/>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>页</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>页</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="menu">
<property name="title">
<string>文件</string>
</property>
<addaction name="action"/>
<addaction name="action_Input"/>
</widget>
<addaction name="menu"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="action">
<property name="icon">
<iconset theme="document-open">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>打开 Open</string>
</property>
</action>
<action name="action_Input">
<property name="text">
<string>导入 Input</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

100
README.md
View File

@@ -1,49 +1,79 @@
# 音·创 Musicreater
<h1 align="center">音·创 Musicreater</h1>
### 介绍
音·创(Musicreater)是由金羿(W-YI)开发的一款《我的世界》基岩版音乐生成辅助软件
<h2 align="center">库版 Package Version</h2>
欢迎加群861684859
<p align="center">
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
</p>
### 软件架构
<p align="center">
<img src="https://forthebadge.com/images/badges/built-with-love.svg">
<p>
软件采用Python作为第一语言目前还没有使用其他语言辅助。使用BeeWare作为图形库兼容安卓。
[![][Bilibili: 凌云金羿]](https://space.bilibili.com/397369002/)
[![][Bilibili: 诸葛亮与八卦阵]](https://space.bilibili.com/604072474)
[![CodeStyle: black]](https://github.com/psf/black)
[![][python]](https://www.python.org/)
[![][license]](LICENSE)
[![][release]](../../releases)
尽量全平台支持
简体中文🇨🇳 | [English🇬🇧](README_EN.md)
## **嘿伙计,你是不是来错地儿了,这里还在开发,注意选对版本!**
## 介绍🚀
音·创 Musicreater 是一款免费开源的 **《我的世界:基岩版》** 音乐制作软件
音·创 库版 (Musicreater Package Version) 是一款免费开源的针对 **《我的世界:基岩版》** 的midi音乐转换库
欢迎加群:[861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr)
**此分支为音·创的包版本即便于其他软件使用的可被import版本**
### **看这看这!看这看这!看这看这!教程:[教程链接](./docs/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md)**
## 软件作者✒
金羿 Eilles我的世界基岩版指令师个人开发者B站不知名UP主江西在校高中生。
诸葛亮与八卦阵 bgArray我的世界基岩版玩家喜欢编程和音乐深圳初二学生。
### 安装教程
#### Windows
## 致谢🙏
即将到来。
- 感谢 **昀梦**\<QQ1515399885\> 找出指令生成错误bug并指正
- 感谢由 **Charlie_Ping “查理平”** 带来的bdx文件转换参考
以及mid转我的世界乐器参考表格
- 感谢由 **CMA_2401PT** 为我们的软件开发进行指导
- 感谢由 **Dislink Sforza “断联·斯福尔扎”**\<QQ1600515314\>带来的midi音色解析以及转换指令的算法我们将其改编并应用同时感谢他的[网页版转换器](https://dislink.github.io/midi2bdx/)给我们的开发与更新带来巨大的压力和动力,让我们在原本一骑绝尘的摸鱼道路上转向开发
- 感谢 **Touch “偷吃”**\<QQ1793537164\>提供的测试支持,并对程序的改进提供了丰富的意见;同时也感谢他的不断尝试新的内容,使我们的排错更进一步
- 感谢 **Mono**\<QQ738893087\>反馈安装时的问题
- 感谢 **Ammelia** 敦促我们进行新的功能开发,并为新功能提出了非常优秀的大量建议
#### Linux
> 感谢广大群友为此程序提供的测试等支持
>
> 若您对我们有所贡献但您的名字没有显示在此列表中,请联系我!
即将到来。
## 联系我们📞
#### Android
即将到来。
### 使用说明
1. 直接运行就好
2. 有不懂的问题来群里问
3. 请理解英文表述
### 致谢
1. 感谢由 [Fuckcraft](https://github.com/fuckcraft) “鸣凤鸽子”等 带来的我的世界websocket服务器功能
2. 感谢 昀梦QQ1515399885 找出指令生成错误bug并指正
3. 感谢由 Charlie_Ping “查理平” 带来的bdx转换功能
4. 感谢由 CMA_2401PT 提供的 BDXWorkShop作为.bdx结构的操作指导
5. 感谢广大群友为此程序提供的测试等支持
6. 若您为我找出了错误但您的名字没有显示在此列表中,请联系我!
### 作者<金羿>联系方式
### 作者\<*金羿*\>(Eilles)联系方式
1. QQ 2647547478
2. 电邮 EillesWan2006@163.com W-YI_DoctorYI@outlook.com
3. 微信 WYI_DoctorYI
2. 电邮 EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
3. 微信 WYI_DoctorYI
4. Telegram [@EillesWan](https://t.me/EillesWan)
### 作者\<*诸葛亮与八卦阵*\>(bgArray)联系方式
1. QQ 4740437765
[Bilibili: 凌云金羿]: https://img.shields.io/badge/Bilibili-%E5%87%8C%E4%BA%91%E9%87%91%E7%BE%BF-00A1E7?style=for-the-badge
[Bilibili: 诸葛亮与八卦阵]: https://img.shields.io/badge/Bilibili-%E8%AF%B8%E8%91%9B%E4%BA%AE%E4%B8%8E%E5%85%AB%E5%8D%A6%E9%98%B5-00A1E7?style=for-the-badge
[CodeStyle: black]: https://img.shields.io/badge/code%20style-black-121110.svg?style=for-the-badge
[python]: https://img.shields.io/badge/python-3.6-AB70FF?style=for-the-badge
[release]: https://img.shields.io/github/v/release/EillesWan/Musicreater?style=for-the-badge
[license]: https://img.shields.io/badge/Licence-Apache-228B22?style=for-the-badge

View File

@@ -1,12 +0,0 @@
Musicreater
===========
**This cross-platform app was generated by** `Briefcase`_ **- part of**
`The BeeWare Project`_. **If you want to see more tools like Briefcase, please
consider** `becoming a financial member of BeeWare`_.
音·创(Musicreater)是由金羿(W-YI)开发的一款《我的世界》基岩版音乐生成辅助软件
.. _`Briefcase`: https://github.com/beeware/briefcase
.. _`The BeeWare Project`: https://beeware.org/
.. _`becoming a financial member of BeeWare`: https://beeware.org/contributing/membership

74
README_EN.md Normal file
View File

@@ -0,0 +1,74 @@
<h1 align="center">音·创 Musicreater</h1>
<p align="center">
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
</p>
<p align="center">
<img src="https://forthebadge.com/images/badges/built-with-love.svg">
<p>
[![][Bilibili: Eilles]](https://space.bilibili.com/397369002/)
[![][Bilibili: bgArray]](https://space.bilibili.com/604072474)
[![CodeStyle: black]](https://github.com/psf/black)
![][python]
[![][license]](LICENSE)
[![][release]](../../releases)
[简体中文🇨🇳](README.md) | English🇬🇧
**Notice that the language support of *README* may be a little SLOW.**
## Introduction🚀
Musicreater(音·创) is a free open source software which is used for making and also creating music in **Minecraft: Bedrock Edition**.
Musicreater pkgver(Package Version 音·创 库版) is a free open source library used for convert midi file into formats that is suitable for **Minecraft: Bedrock Edition**.
Welcome to join our QQ group: [861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr)
### **SEEEEEEEEE Tutorials [HERE](./docs/Use%20of%20Funtions.md)**
### Authors✒
Eilles (金羿)A high school student, individual developer, unfamous BilibiliUPer, which knows a little about commands in *Minecraft: Bedrock Edition*
bgArray "诸葛亮与八卦阵": Fix bugs, improve code aesthetics, add new functions, change data format, etc.
## Thanks🙏
- Thank *昀梦*\<QQ1515399885\> for finding and correcting the bugs in the commands that *Musicreater* Created.
- Thank *Charlie_Ping “查理平”* for bdx convert function, and
the data label that's used to convert the mid's instruments into minecraft's instruments.
- Thank *CMA_2401PT* for BDXWorkShop as the .bdx structure's operation guide.
- Thank *Dislink Sforza* \<QQ1600515314\> for the algorithm brought to us, his midi analysis algorithm became one of us's best ones
- Thank *Arthur Morgan*\<QQ312280061\> for his/her biggest support for the debugging of Musicreater
- Thank *Touch “偷吃”*\<QQ1793537164\> for support of debugging and testing program and algorithm, as well his/her suggestions to the improvement of our project
- Thank *Mono*\<QQ738893087\> for reporting problems while installing
- Thanks for a lot of groupmates who support me and help me to test the program.
- If you have give me some help but u haven't been in the list, please contact me.
## Contact Information📞
### Author *Eilles*(金羿)
1. QQ 2647547478
2. E-mail EillesWan2006@163.com
W-YI_DoctorYI@outlook.com EillesWan@outlook.com
3. WeChat WYI_DoctorYI
4. Telegram [@EillesWan](https://t.me/EillesWan)
### Author *bgArray*(诸葛亮与八卦阵)
1. QQ 4740437765
[Bilibili: Eilles]: https://img.shields.io/badge/Bilibili-%E5%87%8C%E4%BA%91%E9%87%91%E7%BE%BF-00A1E7?style=for-the-badge
[Bilibili: bgArray]: https://img.shields.io/badge/Bilibili-%E8%AF%B8%E8%91%9B%E4%BA%AE%E4%B8%8E%E5%85%AB%E5%8D%A6%E9%98%B5-00A1E7?style=for-the-badge
[CodeStyle: black]: https://img.shields.io/badge/code%20style-black-121110.svg?style=for-the-badge
[python]: https://img.shields.io/badge/python-3.6-AB70FF?style=for-the-badge
[release]: https://img.shields.io/github/v/release/EillesWan/Musicreater?style=for-the-badge
[license]: https://img.shields.io/badge/Licence-Apache-228B22?style=for-the-badge

View File

@@ -1,52 +0,0 @@
# Musicreater
### Introduction
Musicreater(音·创) is an Eilles(*W-YI*)'s app that is used for creating musics in **Minecraft: Bedrock Edition**.
Welcome to join our QQ group: 861684859
### Framework
Use *Python* to develop, use *BeeWare* as a Windows Library.
We are trying to support every platform.
### Tutorials
#### Windows
Please wait for a while...
Comming soon
#### Linux
Please wait for a while...
Comming soon
#### Android
Please wait for a while...
Comming soon
### Instructions
1. Just make u understand the Chinese
2. If u dont understand, u can come to the QQ group or email me to ask questions
3. The English Edition is comming soon.
### Thanks
1. Thank [Fuckcraft](https://github.com/fuckcraft) “鸣凤鸽子”and so on for the function of Creating the Websocket Server for Minecraft: Bedrock Edition.
2. Thank 昀梦QQ1515399885 for finding and correcting the bugs in the commands that *Musicreater* Created.
3. Thank Charlie_Ping “查理平” for bdx convert funtion.
4. Thank CMA_2401PT for BDXWorkShop as the .bdx structure's operation guide.
5. Thanks for a lot of groupmates who support me and help me to test the program.
6. If u have give me some help but u haven't been in the list, please contact me.
### Contact *Eilles(W-YI)*(金羿)
1. QQ 2647547478
2. E-mail EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
3. WeChat WYI_DoctorYI

View File

@@ -1 +0,0 @@
briefcase dev

View File

@@ -1,60 +0,0 @@
# -*- coding: utf-8 -*-
import os,shutil
from sys import platform
print("更新执行位置...")
if platform == 'win32':
try:
os.chdir(__file__[:len(__file__)-__file__[len(__file__)::-1].index('\\')]+'src\\')
print("更新执行位置,当前文件位置"+__file__)
except:
pass
else:
try:
os.chdir(__file__[:len(__file__)-__file__[len(__file__)::-1].index('/')]+'src/')
except:
pass
print("其他平台:"+platform+"更新执行位置,当前文件位置"+__file__)
print('完成!')
try:
import toga,amulet
except:
print("You'd better install the libraries of this app\nNow, we're helping you with this.")
from src.musicreater.msctspt.bugReporter import version
version.installLibraries(version)
if platform == 'win32':
os.system("python ./Musicreater.py")
elif platform == 'linux':
os.system("python3 ./Musicreater.py")
try:
if os.path.exists("./log/"):
shutil.rmtree("./log/")
if os.path.exists("./logs/"):
shutil.rmtree("./logs/")
if os.path.exists("./cache/"):
shutil.rmtree("./cache/")
except:
print("无法清除日志及临时文件")

151
demo_convert.py Normal file
View File

@@ -0,0 +1,151 @@
# -*- coding: utf-8 -*-
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
# 若需转载或借鉴 许可声明请查看仓库目录下的 Lisence.md
"""
音·创 库版 MIDI转换展示程序
Musicreater Package Version : Demo for Midi Conversion
Copyright 2023 all the developers of Musicreater
开源相关声明请见 ./Lisence.md
Terms & Conditions: ./Lisence.md
"""
from msctPkgver.main import *
import os
convertion = midiConvert()
while True:
midipath = input('请输入midi文件路径')
if os.path.exists(midipath):
break
else:
print('文件不存在,请重新输入')
outpath = input('请输入输出路径:')
if not os.path.exists(outpath):
os.makedirs(outpath)
while True:
try:
outFormat = int(input('请输入输出格式(0:mcpack|1:BDX结构)'))
if outFormat == 0:
isAutoReset = input('是否自动重置计分板(1|0)')
if isAutoReset != '':
isAutoReset = bool(int(isAutoReset))
while True:
isProgress = input('*进度条[本Demo不支持自定义]')
if isProgress != '':
if isProgress in ('1', 'True'):
isProgress = True
elif isProgress in ('0', 'False'):
isProgress = False
else:
isProgress = isProgress
else:
continue
break
sbname = input('请输入计分板名称:')
volume = input('请输入音量0-1')
if volume != '':
volume = float(volume)
speed = input('请输入速度倍率:')
if speed != '':
speed = float(speed)
elif outFormat == 1:
author = input('请输入作者:')
while True:
isProgress = input('*进度条[本Demo不支持自定义]')
if isProgress != '':
if isProgress in ('1', 'True'):
isProgress = True
elif isProgress in ('0', 'False'):
isProgress = False
else:
isProgress = isProgress
else:
continue
break
maxHeight = input('请输入指令结构最大生成高度:')
if maxHeight != '':
maxHeight = int(maxHeight)
sbname = input('请输入计分板名称:')
volume = input('请输入音量0-1')
if volume != '':
volume = float(volume)
speed = input('请输入速度倍率:')
if speed != '':
speed = float(speed)
isAutoReset = input('是否自动重置计分板(1|0)')
if isAutoReset != '':
isAutoReset = bool(int(isAutoReset))
break
except BaseException:
print('输入错误,请重新输入')
m = 1
'''采用的算法编号'''
if os.path.isdir(midipath):
for i in os.listdir(midipath):
if i.lower().endswith('.mid'):
print(f'正在操作{i}')
convertion.convert(midipath + '/' + i, outpath + '/' + i[:-4])
if outFormat == 0:
print(convertion.tomcpack(
m,
isAutoReset
if isAutoReset != ''
else bool(int(input('是否自动重置计分板(1|0)'))),
isProgress,
sbname if sbname != '' else input('请输入计分板名称:'),
volume if volume != '' else float(input('请输入音量0-1')),
speed if speed != '' else float(input('请输入速度倍率:')),
))
elif outFormat == 1:
print(convertion.toBDXfile(
m,
author if author != '' else input('请输入作者:'),
isProgress,
maxHeight if maxHeight != '' else int(input('请输入指令结构最大生成高度:')),
sbname if sbname != '' else input('请输入计分板名称:'),
volume if volume != '' else float(input('请输入音量0-1')),
speed if speed != '' else float(input('请输入速度倍率:')),
isAutoReset
if isAutoReset != ''
else bool(int(input('是否自动重置计分板(1|0)'))),
))
else:
convertion.convert(midipath, outpath)
if outFormat == 0:
print(convertion.tomcpack(
m,
isAutoReset if isAutoReset != '' else bool(int(input('是否自动重置计分板(1|0)'))),
isProgress,
sbname if sbname != '' else input('请输入计分板名称:'),
volume if volume != '' else float(input('请输入音量0-1')),
speed if speed != '' else float(input('请输入速度倍率:')),
))
elif outFormat == 1:
print(convertion.toBDXfile(
m,
author if author != '' else input('请输入作者:'),
isProgress,
maxHeight if maxHeight != '' else int(input('请输入指令结构最大生成高度:')),
sbname if sbname != '' else input('请输入计分板名称:'),
volume if volume != '' else float(input('请输入音量0-1')),
speed if speed != '' else float(input('请输入速度倍率:')),
isAutoReset if isAutoReset != '' else bool(int(input('是否自动重置计分板(1|0)'))),
))

101
demo_convert_bdx_byDelay.py Normal file
View File

@@ -0,0 +1,101 @@
# -*- coding: utf-8 -*-
# THIS PROGRAM IS ONLY A TEST EXAMPLE
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
# 若需转载或借鉴 许可声明请查看仓库目录下的 Lisence.md
"""
音·创 库版 MIDI转换展示程序
Musicreater Package Version : Demo for Midi Conversion
Copyright 2023 all the developers of Musicreater
开源相关声明请见 ./Lisence.md
Terms & Conditions: ./Lisence.md
"""
from msctPkgver.main import *
convertion = midiConvert()
while True:
midipath = input('请输入midi文件路径')
if os.path.exists(midipath):
break
else:
print('文件不存在,请重新输入')
outpath = input('请输入输出路径:')
if not os.path.exists(outpath):
os.makedirs(outpath)
while True:
try:
authorname = input('请输入作者:')
while True:
isProgress = input('*进度条[本Demo不支持自定义]')
if isProgress != '':
if isProgress in ('1', 'True'):
isProgress = True
elif isProgress in ('0', 'False'):
isProgress = False
else:
isProgress = isProgress
else:
continue
break
volume = input('请输入音量0-1')
if volume != '':
volume = float(volume)
speed = input('请输入速度倍率:')
if speed != '':
speed = float(speed)
player = input('请输入玩家选择器:')
heightmax = input('请输入指令结构最大生成高度:')
if heightmax != '':
heightmax = int(heightmax)
break
except BaseException:
print('输入错误,请重新输入')
def operation(
i,
):
print(f'正在操作{i}')
convertion.convert(midipath + '/' + i, outpath)
convertion.toBDXfile_withDelay(
1,
authorname if authorname != '' else input('请输入作者:'),
isProgress,
heightmax if heightmax != '' else int(input('请输入指令结构最大生成高度:')),
volume if volume != '' else float(input('请输入音量(0-1]')),
speed if speed != '' else float(input('请输入速度倍率:')),
player if player != '' else input('请输入玩家选择器:'),
)
if os.path.isdir(midipath):
import threading
for i in os.listdir(midipath):
if i.lower().endswith('.mid'):
threading.Thread(target=operation, args=(i,)).start()
else:
convertion.convert(midipath, outpath)
convertion.toBDXfile_withDelay(
1,
authorname if authorname != '' else input('请输入作者:'),
isProgress,
heightmax if heightmax != '' else int(input('请输入指令结构最大生成高度:')),
volume if volume != '' else float(input('请输入音量(0-1]')),
speed if speed != '' else float(input('请输入速度倍率:')),
player if player != '' else input('请输入玩家选择器:'),
)

262
docs/Use of Funtions.md Normal file
View File

@@ -0,0 +1,262 @@
<h1 align="center">音·创 Musicreater</h1>
<p align="center">
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
</p>
# Instructions for Using Demo(s)
*This is a tutorial for using the demo(s) of this library, not the Development Guide. If you want to see so, please read Below*
## Under Windows
0. Install Python 3.6+
First of all, you need to install the runtime environment of this library, *Python*. And a Installation Pack maybe the best choice:
> [Downloading Python 64-bit](https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe)
> [Downloading Python 32-bit](https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe)
While installing, it's better to check `Add Python 3.X to PATH`(just as the screenshot showed below), otherwise it needs to be set manually which may cause some time wasting
<img src=https://foruda.gitee.com/images/1662736520757331846/e38efb81_9911226.png>
If you are new to Python or not very familiar to Computer Programming, and having the disk space in your PC's System Partition (usually C:) of 150 MB, you can directly choose *Install Now*.
However, if you want to do it like a pro, choosing *Customize Installation*, it's a necessary to be sure to check `pip` and `py launcher` will be installed on your computer(see screenshot below). The two options is required for the next step of installing the requirements.
<img src=https://foruda.gitee.com/images/1662736621235871190/2ac3d98f_9911226.png>
After the installation, you can enter in your terminal(CMD/PowerShell/Bash/etc): "python" to ensure whether the installation was successful. If it was, your terminal will show things like below:
<img src=https://foruda.gitee.com/images/1659972669907359295/cmd.png>
1. Installing Requirements
It's better to open your terminal(CMD/PowerShell/Bash/etc) under Administrator Mode.
For example, if you want to use CMD in Administrator Mode, you can search `cmd` in the *Start Menu*, right click it and *Run as Administrator*
<img src="https://foruda.gitee.com/images/1662736878650993886/62487dd8_9911226.png">
Okay, after that, please enter in your terminal:
`pip install mido`
`pip install brotli`
If successful you will see something like below:
<img src="https://foruda.gitee.com/images/1662737676719454287/f61a70f7_9911226.png">
2. Download This Package and Demo(s)
- If you using Git, you can use the following commands to clone this lib:
`git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git`
- If Git is not installed, you can download the zip package from the code page(from [GitHub](https://github.com/EillesWan/Musicreater.git) or [Gitee](https://gitee.com/EillesWan/Musicreater.git)). Or you are a Chinese fan having a QQ account, you can [Join the QQ Group 861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr) and get it from our GroupFiles.
<img src=" https://foruda.gitee.com/images/1659972440341216712/下载.png" >
2. Start Using Demo(s)
Open your terminal in the directory of this, taking CMD, for example, just enter the directory and enter `cmd` in the path box:
<img src=https://foruda.gitee.com/images/1659974437388532868/输入.png>
<img src=https://foruda.gitee.com/images/1659974754378201859/输入c.png>
And enter one of the commands below by choosing what you need:
`python demo_convert.py`
`python demo_convert_bdx_byDelay.py`
### Addition for Error(s) Using or Installing
1. Environment Error of Microsoft Visual C++ Redistributable
If you meet this condition as the screenshot shows:
<img src=https://foruda.gitee.com/images/1659972789779764953/bug.jpeg>
Your MSVC Environment may be not installed, and you can download and install
> [Here of 64-Bit VCREDIST](https://aka.ms/vs/17/release/vc_redist.x64.exe)
> [Here of 32-Bit VCREDIST](https://aka.ms/vs/17/release/vc_redist.x86.exe)
Thank our groupmate *Mono* again for helping finding this problem.
## Under Linux OS
### Install Runtime Environment
0. Install and Verify Python Runtime
Common Linux Releases do include a Python Runtime Environment, what we should do only is to check it is a satisfied version to our program. If the version ≥Python3.6, theoretically our program can be run.
We can type:
```bash
python -V
```
To check the Python version, as the follows
<img src=https://foruda.gitee.com/images/1665120915821957090/429561fd_9911226.png>
- Not Necessary
If you want to change a Python version just as what I want to do, it is such a great fantastic action! Let do as the follows:
- pacman Package ManagerIn Arch Linux Mostly
Let's write python3 into the ingore list of updating. Via `vim` to edit `/etc/pacman.conf`, add `python3` after `IgnorePkg`.
```bash
sudo vim /etc/pacman.conf
```
<img src=https://foruda.gitee.com/images/1665124611490335193/5e99ca26_9911226.png>
Then we can search for python releases in [Arch Achieve](https://archive.archlinux.org/packages/).*HERE, under Arch, Python refers to Python3 defaultly, while some other Linux releases using Python2 as default. So dose Arch Achieve.*What I find here is [Python3.8.6](https://archive.archlinux.org/packages/p/python/python-3.8.6-1-x86_64.pkg.tar.zst), so let's download she via `pacman`:
```bash
sudo pacman -U https://archive.archlinux.org/packages/p/python/python-3.8.6-1-x86_64.pkg.tar.zst
```
<img src=https://foruda.gitee.com/images/1665126362769399903/ea4b9598_9911226.png>
Perfect!
1. Install and Verify pip Package Manager
Before installing, it is to be checked, wheather Python's pip is OK:
```bash
python -m pip # To check is pip installed
# If a long tip occured, it is OK
# If returned as this, then not.
/usr/bin/python: No module named pip
# We can install pip via:
sudo pacman -S python-pip
# Verfy, remember.
python -m pip
# If you did but failed, we should use other methods to install pip:
wget https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
# Verfy, must.
python -m pip
```
Over after checking, lets install the dependences.
```bash
pip install mido -i https://mirrors.aliyun.com/pypi/simple/
pip install brotli -i https://mirrors.aliyun.com/pypi/simple/
```
See the tips below as successfully installed
<img src="https://foruda.gitee.com/images/1662737676719454287/f61a70f7_9911226.png">
### Download this sources pack and Using its demos.
1. 使用Git下载本库及其示例代码
```bash
git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git MSCTpkgver
```
当上述命令执行成功,你会在执行此命令的所在位置发现一个名为 `MSCTpkgver` 的文件夹,其中包含的正是我们心心念念下载的本程序和示例代码。
而我们要运行的也正是示例代码,因此,赶快进入下载到的文件夹:
```bash
cd MSCTpkgver
```
1. 开始使用
在目录下打开终端,执行以下命令:(选择你需要的)
```bash
python demo_convert.py
python demo_convert_bdx_byDelay.py
```
2. More Info for Parameters of Our Demo Program(s)
<img src=https://foruda.gitee.com/images/1659974810147043475/运行.png>
|Input Prompt|English Translation|Description|
|----------------|----------------|-------|
|请输入MIDI文件路径|Midi File Path|Path of a .mid file or a directory. While directory entered, our demo will convert all midi(s) in the directory|
|请输入输出路径|Output Path|Where files converted in|
|是否重置计分板|Whether Reset Scoreboard Automatically|Can only be 1 or 0(Recommanded 1)|
|*进度条[注]|Progressbar|Whether to enable Progressbar and customize progressbar style. Type 0 or False to disable, 1 or True to use default style, or type using format taught in follow the Instructions below to customize one you like|
|请输入计分板名称|Scoreboard Name|*Only not byDelay* The name of scoreboard that player using|
|请输入音量|Volume|Only decimal in [0,1],(Recommanded 1)|
|请输入速度倍率|Speed Multiplying Factor|Maybe you want to play it faster(1) or slower(0 1)?|
|请输入玩家选择器|Player Selector|Full Selector including `@x`. E.g: Play for players tagged `Holo`, enter `@a[tag=Holo]` on this parameter|
# Instructions for **Customize Progress Bar**
We have supported the function of making progress bar in *Minecraft*'s music player. And also the method of customize them. So the following instructions are about the parameters of the Progress Bar Customizition.
A Progress Bar, of course, is composed of **changeless** parts and **changable** parts. And the changable parts include texts or *images*(these images are made up of texts, or we can say, character paintings 😁). That is, for *Minecraft*, a changable image in a progress bar is just the "bar" part(which is like a stripe).
We use a string to describe the style of progress bar you need, and it includes many **identifier**s to replace the changable parts.
There are the identifiers:
| Identifier | Changable Part |
|--------------|------------------------------------------------------|
| `%%N` | Music name(file name which is imported into program) |
| `%%s` | Value of scoreboard of now |
| `%^s` | Max value of scoreboard |
| `%%t` | Current playback time |
| `%^t` | Total music time |
| `%%%` | Current playback progress |
| `_` | To be replaced by the *Bar* part of the progress bar |
The `_` is a placeholder to identifying the *bar* part, yeah, just the changable image.
This is an example of **style description string**, and this is also the default style of *Musicreater*'s progress bar.
`▶ %%N [ %%s/%^s %%% __________ %%t|%^t]`
This is a progress bar with only one line, but it is possible if you want to give a multiline parameter into the style description string.
But the string above is only for style identification, but we also need to identifying the changable image's image(just what the bar's look).
A "bar", simply, included 2 parts: *Have Been Played* & *Not Been Played*. So we use a tuple to pass the parameter. It's under a simple format: `(str: played, str: not)`. For example, the default parameter is below:
`('§e=§r', '§7=§r')`
So it's time to combine what I said in one parameter now!
This is a default definder parameter:
`('▶ %%N [ %%s/%^s %%% __________ %%t|%^t]',('§e=§r', '§7=§r'))`
*Tip: To avoid errors, please not to use the identifiers as the other part of your style.*

View File

@@ -0,0 +1,167 @@
## 使用前的准备工作
### 安装终端工具
这里我们选用 **Termux** 作为我们的终端工具来安装这是一个强大的终端模拟器旨在安卓环境下模拟Linux的软件包环境。
1. 下载
下载可以通过 [GitHub源](https://github.com/termux/termux-app/releases) 或者 [F-Droid源](https://f-droid.org/en/packages/com.termux/) ,个人建议选择 F-Droid 源,因为在国内可以访问得到,而 GitHub 源就看运气。
2. 安装
下载*APK*包后直接安装,安装后打开可以看到一个类似这样的界面:
<img height="512" src="https://foruda.gitee.com/images/1665933025120627254/a0479618_9911226.jpeg">
3. 完成
恭喜你,你已经获得了一个极客般流畅地操作你手机的终端工具。
### 安装运行环境
1. 换源
接下来,我们就要来准备安装一下 **Python** 运行环境了,这是运行 **Python** 源代码必要的。
首先,我估计你等不了多久,急得要死,所以我们要让下载速度稍微快一点,先来换个源。在 **Termux** 中,输入以下指令:
```bash
echo "deb https://mirror.mwt.me/termux/main stable main" > /data/data/com.termux/files/usr/etc/apt/sources.list
```
*感谢 天如<QQ 3291691454>为我们带来的简单换源方法。*
- *非必要步骤*:手动编辑换源
如果你闲着没事,非要要手动编辑个文档来换源,那用啥?用普通的编辑器肯定可以,于是我们就让他更普通一点,用**nano**吧!
在 **Termux** 中,输入以下指令:
```bash
export EDITOR=nano
apt edit-sources
```
那么请把看到的如左下图的界面变为右下图吧:
<table><tr>
<td><img src="https://foruda.gitee.com/images/1665933104313107707/41108f03_9911226.jpeg"> </td>
<td><img src="https://foruda.gitee.com/images/1665933122534781330/3887a901_9911226.jpeg"></td>
</tr></table>
- 图片中的文件,最后应该加入的两行为:
```bash
deb https://mirrors.ustc.edu.cn/termux/apt/termux-main/ stable main
deb https://mirrors.tuna.tsinghua.edu.cn/termux/apt/termux-main/ stable main
```
然后键入 `Ctrl`+`S`,再键入 `Ctrl`+`X`,退出`nano`。
在换源之后,你可能会见到类似的提示:
```bash
Your '/data/data/com.termux/files/usr/etc/apt/sources.list' file changed. Please run 'apt-get update'.
```
那就遵循它的指引,输入:
```bash
apt-get update
```
Alright.
2. 安装 **Python**
```bash
apt-get install python3
```
如果遇到提示问是否继续,那就输入`Y`表示是,如左下图,安装成功后,图若右下。
<table><tr>
<td><img src="https://foruda.gitee.com/images/1665933181440420034/7f0fb5fd_9911226.jpeg"></td>
<td><img src="https://foruda.gitee.com/images/1665933238339972260/a9f06f4f_9911226.jpeg"></td>
</tr></table>
接下来,我们来试一试 **Python** 是不是安装成了吧,输入
```bash
python3 -V
```
如果输出了形如 `Python 3.X.X` 的提示,则完成。
3. 安装依赖库
```bash
# 首先换源
pip config set global.index-url http://mirrors.aliyun.com/pypi/simple/
# 然后安装
pip install mido
pip install brotli
```
- 如果出现以下情况,真是死了鬼的,我们要来再搞个设置:
<img height="512" src="https://foruda.gitee.com/images/1665933289612919459/b87b7804_9911226.jpeg">
我们来修改收信任的源设置:
```bash
pip config set global.trusted-host mirrors.aliyun.com/
```
之后再来安装即可
```bash
pip install mido
pip install brotli
```
安装成功后您可能会见到类似下图的提示:
<img src="https://foruda.gitee.com/images/1662737676719454287/f61a70f7_9911226.png">
### 安装下载工具
既然已经有了运行环境,那么我们就需要下载下我们的**音·创库版示例代码**工具,我非常推崇**Git**这种方便快捷好用还能下载仓库的代码管理器,这个世界上你也找不到第二个,所以我们来安装一下:
```bash
pkg install git
```
安装完成后记得测试一下:
<img height="512" src="https://foruda.gitee.com/images/1665933331269483373/9374c85d_9911226.jpeg">
## 本代码库的下载与演示程序的使用
1. 使用Git下载本库及其示例代码
```bash
git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git MSCTpkgver
```
当上述命令执行成功,你会在执行此命令的所在位置发现一个名为 `MSCTpkgver` 的文件夹,其中包含的正是我们心心念念下载的本程序和示例代码。
而我们要运行的也正是示例代码,因此,赶快进入下载到的文件夹:
```bash
cd MSCTpkgver
```
1. 开始使用演示程序
依照你的需要,执行以下命令之一:
```bash
python demo_convert.py #计分板播放器支持mcpack与BDX
python demo_convert_bdx_byDelay.py #延迟播放器仅支持BDX
```
运行成功了,哦耶!
<img height="512" src="https://foruda.gitee.com/images/1665933366784631363/db9f80f6_9911226.jpeg">

View File

@@ -0,0 +1,104 @@
## 运行环境安装
### 检验Python运行环境
0. 一般的Linux发行版都有安装Python环境我们只需要保证其版本即可理论上 ≥Python3.6 都可以运行我们的库
我们可以使用
```bash
python -V
```
来查看 Python 版本,如下
<img src=https://foruda.gitee.com/images/1665120915821957090/429561fd_9911226.png>
1. *非必要环节*:回退版本
如果你跟作者一样,觉得 Python 3.10+ 太难用很烦人的话,那真是皆大欢喜,让我们一起来回退版本吧!
- pacman 包管理器多用于Arch Linux上
1. 让我们先来把 python3 加入忽略升级的列表中,使用`vim`修改`/etc/pacman.conf`,在`IgnorePkg`后加上`python3`
```bash
sudo vim /etc/pacman.conf
```
<img src=https://foruda.gitee.com/images/1665124611490335193/5e99ca26_9911226.png>
2. 然后我们开始从[Arch Achieve](https://archive.archlinux.org/packages/)上找Python的版本列表。*这里说明一下在Arch中Python默认指的是Python3而与其他某些Linux发行版中Python默认指代Python2不同所以在Arch Achieve中也是如此。*)我这里找到的是[Python3.8.6](https://archive.archlinux.org/packages/p/python/python-3.8.6-1-x86_64.pkg.tar.zst),于是我们用`pacman`把她下载下来并安装:
```bash
sudo pacman -U https://archive.archlinux.org/packages/p/python/python-3.8.6-1-x86_64.pkg.tar.zst
```
<img src=https://foruda.gitee.com/images/1665126362769399903/ea4b9598_9911226.png>
3. 完美!
- 其他包管理器
暂无
### 检查并安装pip包管理器依赖
1. 我们在安装依赖库之前应该确认一下Python自带的包管理器pip是否安装到位
```bash
python -m pip # 确认pip是否安装
# 当这个命令输入后有长段提示出现则为已经安装
# 如果返回如下那么则pip尚未安装
/usr/bin/python: No module named pip
# 可以使用如下命令来安装pip
sudo pacman -S python-pip
# 安装完成后记得验证
python -m pip
# 如果还是失败那么就需要用其他工具安装pip
wget https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
# 安装完成后一定要验证!!!
python -m pip
```
2. 确认完成之后,我们来安装一下依赖库:
```bash
pip install mido -i https://mirrors.aliyun.com/pypi/simple/
pip install brotli -i https://mirrors.aliyun.com/pypi/simple/
```
3. 安装成功后可能会见到类似下图的提示:
<img src="https://foruda.gitee.com/images/1662737676719454287/f61a70f7_9911226.png">
## 本代码库的下载与使用
1. 使用Git下载本库及其示例代码
```bash
git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git MSCTpkgver
```
当上述命令执行成功,你会在执行此命令的所在位置发现一个名为 `MSCTpkgver` 的文件夹,其中包含的正是我们心心念念下载的本程序和示例代码。
而我们要运行的也正是示例代码,因此,赶快进入下载到的文件夹:
```bash
cd MSCTpkgver
```
1. 开始使用
在目录下打开终端,执行以下命令:(选择你需要的)
```bash
python demo_convert.py #计分板播放器支持mcpack与BDX
python demo_convert_bdx_byDelay.py #延迟播放器仅支持BDX
```

View File

@@ -0,0 +1,89 @@
## 一、运行环境安装
### (一)安装 Python3.6+
1. 首先需要下载Python的安装包最好是 *Python3.8*,因为作者就用的是这个版本
> [下载64位Python安装包](https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe)
> [下载32位Python安装包](https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe)
2. 在安装时,最好需要勾选 `Add Python 3.X to PATH`,如下图所示,当然,如果您对自己非常自信,您也可以手动设置此项目:
<img src=https://foruda.gitee.com/images/1662736520757331846/e38efb81_9911226.png>
- 若您对Python一知半解或者不怎么了解、并对自己的系统盘通常是C盘有大约150*兆字节*(MB)的信心的话,您可以在安装时直接选择*快速安装*(Install Now)
3. 若您选择了*自定义安装*(Customize Installation),请务必勾选 `pip``py launcher` 便于后续安装依赖,如下图:
<img src=https://foruda.gitee.com/images/1662736621235871190/2ac3d98f_9911226.png>
4. 安装结束之后可以在*终端*(命令行/PowerShell/Bash/etc)中输入python 试试是否安装成功成功安装之后在终端中输入python会显示诸如如下图片的提示
<img src=https://foruda.gitee.com/images/1659972669907359295/cmd.png>
### (二)安装依赖
1. 请以管理员模式打开您的*终端*(命令行/PowerShell/Bash/etc)
例如,命令行,可以如此打开:在*视窗开始菜单*(Windows开始)中搜索 `cmd`, 并以管理员身份运行
<img src="https://foruda.gitee.com/images/1662736878650993886/62487dd8_9911226.png">
2. 打开了终端之后,请在终端中输入以下指令
```bash
pip install mido -i https://mirrors.aliyun.com/pypi/simple/
pip install brotli -i https://mirrors.aliyun.com/pypi/simple/
```
3. 安装成功后您可能会见到类似下图的提示:
<img src="https://foruda.gitee.com/images/1662737676719454287/f61a70f7_9911226.png">
## 二、本工具的下载与使用
0. 下载本代码库以及演示程序
- 若您使用git请直接克隆本仓库
```bash
git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git
```
- 若您不使用git可以在[*码云*(Gitee)](https://gitee.com/EillesWan/Musicreater.git)或[*GitHub*](https://github.com/EillesWan/Musicreater.git)下载zip包或者[加入QQ群聊861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr),在群文件中获取。
<img src="https://foruda.gitee.com/images/1669540786443169766/fabf0acd_9911226.png" >
值得注意的是这张图上有1、2两个数字虽然是手写的但确实是数字表示着要进行的步骤。希望眼尖得能找出我的口头禅的你们能够发现这两个用鼠标手写的数字并在安装时认真地执行。我认为这并不算十分的难移动鼠标并单击大约消耗不了多少卡路里不过我没有进行精确的计算我也不是十分的清楚这个活动对于一个常人来讲有多难但我怀疑它不难。
1. 开始使用
在目录下打开终端。
例如:打开命令行:请进入到目录下,在文件资源管理器的地址框内输入`cmd`
<img src=https://foruda.gitee.com/images/1659974437388532868/输入.png>
<img src=https://foruda.gitee.com/images/1659974754378201859/输入c.png>
执行以下命令:(选择你需要的)
```bash
python demo_convert.py #计分板播放器支持mcpack与BDX
python demo_convert_bdx_byDelay.py #延迟播放器仅支持BDX
```
## 三、安装时错误的补充说明
1. Microsoft Visual C++ Redistributable 环境出错
如果你遇到了类似以下这种情况:
<img src=https://foruda.gitee.com/images/1659972789779764953/bug.jpeg>
请下载最新的VCREDIST安装包可以参照[这个网页](https://docs.microsoft.com/zh-CN/cpp/windows/latest-supported-vc-redist)的说明,也可以在这直接选择你需要的安装包下载:
> [下载64位VCREDIST安装包](https://aka.ms/vs/17/release/vc_redist.x64.exe)
> [下载32位VCREDIST安装包](https://aka.ms/vs/17/release/vc_redist.x86.exe)
感谢群友Mono帮我们发现这个问题。

105
docs/功能使用说明.md Normal file
View File

@@ -0,0 +1,105 @@
<h1 align="center">音·创 Musicreater</h1>
<h2 align="center">库版 Package Version</h2>
<p align="center">
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
</p>
# 演示程序使用教程
*由于先前的 **读我文件**(README.md) 过于冗杂,现另辟蹊径来给大家全方位的教程。*
*这是演示程序demo的使用教程将在这里提供演示程序的相应的使用教程*
## 下载与启动教程
### [视窗(Windows)操作系统](./download%26atart/Windows.md)
### [里纽克斯(Linux)操作系统](./download%26atart/Linux.md)
### [安卓(Android)与安卓衍生操作系统](./download%26atart/Android.md)
## 演示程序使用教程
1. 参数说明
<img src=https://foruda.gitee.com/images/1659974810147043475/运行.png>
- midi路径含有mid文件路径、文件名、后缀的完整文件路径或者一个目录demo可接受批量转换。可以使用相对或绝对路径皆可
- 输出路径:输出文件夹的路径,不需要指示文件名
- 是否重置计分板:`1``0`(歌曲放完是否重置,推荐`1`
- 进度条:是否启用进度条,以及自定义进度条样式。输入`0``False`表示不启用进度条,输入`1``True`表示使用默认进度条,其余的输入均表示使用输入的格式作为自定义的进度条样式
若不支持自定义,则仅能输入`0``1`表示“关闭”或“开启”
- 计分板名称:游戏内的计分板名称
- 音量0-1之间的小数含01正常来说推荐`1`
- 速度倍率小数数据其值不可为0一般写`1`
- 玩家选择器:包括 `@x` 在内的全部选择器,即若要选择全部标签为`Holo`的玩家,则需要如此输入:`@a[tag=Holo]`
- 没有报错且在输出路径下找到mcpack或bdx即为生成成功
<img src=https://foruda.gitee.com/images/1659973655881460036/输出.png>
# 其他说明
## 对于 延迟播放器 的说明
问1什么是延迟播放器
答1播放音乐不同的音符之间存在间隔可以用不同的方式实现音符间空白的时间。其一是计分板通过给计分板加分对应分数播放对应的音符就可以间隔到还有就是命令方块自带的延迟这样也可以实现音符间空白。延迟播放器即后者但是因为只能对命令方块写入这样的延迟数据所以仅可以使用包含NBT的结构导出或者直接输出至世界。
问2可不可以不要积分板
答2详见问1切换你所需要的播放器即可。
## 对于 进度条自定义 功能的说明
因为我们提供了可以自动转换进度条的功能,因此在这里给出进度条自定义参数的详细解释。
请注意,并非所有的演示样例程序都支持自定义进度条。
一个进度条,明显地,有**固定部分**和**可变部分**来构成。而可变部分又包括了文字和图形两种(当然,《我的世界》里头的进度条,可变的图形也就是那个“条”了)。这一点你需要了解,因为后文中包含了很多这方面的概念需要你了解。
进度条的自定义功能使用一个字符串来定义自己的样式,其中包含众多**标识符**来表示可变部分。
标识符如下(注意大小写):
| 标识符 | 指定的可变量 |
|---------|----------------|
| `%%N` | 乐曲名(即传入的文件名)|
| `%%s` | 当前计分板值 |
| `%^s` | 计分板最大值 |
| `%%t` | 当前播放时间 |
| `%^t` | 曲目总时长 |
| `%%%` | 当前进度比率 |
| `_` | 用以表示进度条占位|
表示进度条占位的 `_` 是用来标识你的进度条的。也就是可变部分的唯一的图形部分。
**样式定义字符串**的样例如下,这也是默认的进度条的样式:
`▶ %%N [ %%s/%^s %%% __________ %%t|%^t]`
这是单独一行的进度条,当然你也可以制作多行的,如果是一行的,输出时所使用的指令便是 `title`,而如果是多行的话,输出就会用 `titleraw` 作为进度条字幕。
哦对了,上面的只不过是样式定义,同时还需要定义的是可变图形的部分,也就是进度条上那个真正的“条”。
对于这个我们就采用了固定参数的方法,对于一个进度条,无非就是“已经播放过的”和“没播放过的”两种形态,所以,使用一个元组来传入这两个参数就是最简单的了。元组的格式也很简单:`(str: 播放过的部分长啥样, str: 没播放过的部分长啥样)` 。例如,我们默认的进度“条”的定义是这样的:
`('§e=§r', '§7=§r')`
综合起来,把这些参数传给函数需要一个参数整合,你猜用的啥?啊对对对,我用的还是元组!
我们的默认定义参数如下:
`(r'▶ %%N [ %%s/%^s %%% __________ %%t|%^t]',('§e=§r', '§7=§r'))`
*对了!为了避免生成错误,请尽量避免使用标识符作为定义样式字符串的其他部分*

180
docs/新手答疑指南.md Normal file
View File

@@ -0,0 +1,180 @@
<h1 align="center">音·创 Musicreater</h1>
<h2 align="center">库版 Package Version</h2>
<p align="center">
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
</p>
# 新手答疑指南
**考虑到某些用户电脑技术不是特别先进,且对这个项目充满了好奇心,但是又了解的不是很充分,
为此,我特别在这里写一份文档,解答各位的好奇心。放心,本文件全程中文,英文版本随后更新!**
## 第一部分 关于音·创的作用
### 1.1 音·创简介
音·创 Musicreater 是一款免费开源的 **《我的世界:基岩版》** 音乐制作软件
音·创 库版 (Musicreater Package Version) 是一款免费开源的针对 **《我的世界:基岩版》** 的midi音乐转换库
音·创 采用的是**带有特殊条款的Apache2.0**开源协议,详情请见[这里](https://gitee.com/EillesWan/Musicreater/blob/master/LICENSE.md)。
音·创
目前已经具备较为完善的**教程**,如果你还不知道音·创有教程,请点击
[
这里](https://gitee.com/EillesWan/Musicreater/blob/pkgver/docs/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md)。
### 1.2 音·创到底目前有什么功能?
* - [x] 支持导入.mid文件
* - [x] 支持写入.mcpack文件
* - [x] 支持写入.bdx文件
* 不支持导入.mp3 .mp4 .wav等音频流文件
## 第二部分 关于格式的问题
### 2.1 关于.mid格式
其实对于经常玩音乐电子制作的朋友们来说mid格式并不陌生这里我简单介绍一下。
> mid格式是由MIDI继承而来。MID文件并不是一段录制好的声音而是记录声音的信息然后再告诉声卡如何再现音乐的一组指令。
> 这样一个MIDI文件每存1分钟的音乐只用大约510KB。今天MID文件主要用于原始乐器作品、流行歌曲的业余表演、游戏音轨以及电子贺卡等。
>
> ——百度百科
>
> MIDI 音乐,保存在电脑上,就是 *.mid 类型的文件。和一般意义上的“音乐”不同mid 类型的音乐通常并不是可直接发行供大众欣赏的音乐,
> 它更像是一种音乐创作者使用的工程文件。它没有歌词,不含有人类语言。如果说五线谱是给人类阅读的乐谱,
> MIDI音乐文件便是给计算机或其他电子设备使用的乐谱。对于“音乐”这个世界来说它微不足道却又是现代数字音乐的基石。虽不为大众所知
> 但在 MIDI 音乐爱好者眼中,它却是非常有意思的东西。有了 MIDI 音乐技术和一台电脑,基本就等于拥有了一个乐队,加上相关的音乐知识,
> 就可以自己指挥这个“乐队”,创作音乐作品了!
> 同时MIDI 技术由于数据结构简单又与音乐有关也成为了部分技术极客的爱好。有人使用MIDI技术+Arduino开源硬件制作了架子鼓
> 有人通过分析大量MIDI乐曲结构设计了人工智能作曲软件还有更酷的人使用MIDI音乐制作了随节奏变幻的特斯拉线圈
> 在MIDI 音乐的世界里汇聚了一批喜欢音乐又热爱技术的人。我们有理由相信玩MIDI音乐的你定是多才多艺的。
>
> ——midishow.com
**所以mid文件的本质是电子乐谱而不是记录声音波形文件的.mp3/.wav/.m4a等等文件**
### 2.2 关于.mid格式的获取
通过刚刚的介绍,你可能已经发现,*.mid文件因为受众并不多而并没有被广泛熟知因而你之前可能完全没见过这个文件更何况要弄一首自己心仪的歌了。
这里介绍几个获取.mid格式的方法
1. 最简单的方法就是成为一个作编曲的人,当然,很多人做不到这一点,但是有必要提到这一点,当你在下面的渠道中都无法获得想要的文件时,
你应该考虑是不是需要自己创作内容,或者,请别人帮你创作内容。
2. 当你没有这样的文件时,问问别人或者从群里下在公告的免费的也是个思路,不过这个办法通常使用次数有限。
3. 自己找mid现在我将给你提供一个完整的找mid的方法请认真学习
**1.** 首先你需要在www.midishow.com中注册一个账号并不复杂你可能只需要一个QQ号。
**2.** 登录你的账号,主界面应该如下图所示:
<img src="https://foruda.gitee.com/images/1672644995747340749/36c9c143_10062986.png">
**3.** 在显眼的搜索框中,输入你想要的歌曲名称,接下来的教程,我以`夜空中最亮的星`这首歌及它的mid来演示下载流程。点击搜索框完成这一步。
<img src="https://foruda.gitee.com/images/1672645340943813483/44d0db69_10062986.png">
**4.** 接下来看到搜索结果如下,你可以点进去一个听听,决定你是否要下载;也有可能你什么都没搜到,那你就得换首歌或者换个途径了。
<img src="https://foruda.gitee.com/images/1672645574402099694/6b7e18e5_10062986.png">
**5.** 点击播放按钮试听,网站上的效果可能一般,但是会听音乐的人应该很快就能决定你是否需要下载这个音乐。如果需要下载,你可以进行到下一步,
如果不行,那你可以退回刚刚的页面换一个。
<img src="https://foruda.gitee.com/images/1672645752246438160/47cead78_10062986.png">
**6.** 翻到最下面,如图,你可以对这首歌进行打分,打分可以使积分+1建议打5分你可以对这首歌进行评论一次有意义的评论可以+3分。
下载一首歌需要-3积分如果你先完成了这两项操作再下载那你还会再赚1积分。所以推荐这样做
<img src="https://foruda.gitee.com/images/1672646433045265565/26ea29b2_10062986.png">
**完成后会像这样:**
<img src="https://foruda.gitee.com/images/1672646242419857480/5e8809b8_10062986.png">
**7.** 接下来下载,往上翻网页,找到这个标识,然后单击。
<img src="https://foruda.gitee.com/images/1672646275215822535/63b402db_10062986.png">
**8.** 确认完毕后点击下载。
<img src="https://foruda.gitee.com/images/1672646309787744490/f459adac_10062986.png">
**9.** 完成下载,如图:
<img src="https://foruda.gitee.com/images/1672646335942429563/2449ed0b_10062986.png">
4. 使用mp3转换为mid的工具不得不说科技的进步带来了许多便利让这样困难的事情也变得简单。如果上述方法仍然没有解决你的问题
那么你可以在下一章节中找到有关这个途径的说明。
### 2.3 .mp3格式转换为.mid格式
**注意,使用这个技术有一定难度,酌情使用!**
概述mp3转mid需要把**模拟的波形频谱信号转为数字乐谱信号**,这个过程**一定有损失**。
请各位以后不要在答疑群中问类似于我这个转换效果为什么不好这样的问题,谢谢。
如果直接用**widi**的话相当于对声音进行了**傅里叶变换**,你确实可以分离出其中的音高,但是效果在不同情况下差异较大,
尤其是有架子鼓啊啥的玩也的时候,比较**差**。
[widi工具链接](https://pan.baidu.com/s/1j_Jui0piQ6rMOXM0GJtqTg) 提取码b0lw
**如果只有钢琴的谱子需要分离,有一个完美的选择**[这里](https://zhuanlan.zhihu.com/p/270999354)
如果不然有其他的乐器也需要分离那么可能就有点困难像cakewalk就确实也可以吧音频变成mid但是可能要
**先把原MP3分离成人声音轨、贝斯音轨等再傅里叶变换。**
当然我也可能了解的不全,没准现在已经有传新的技术可以分离的更好了,那就太棒了!(〃'▽'〃)
另外我们开发者也象征性的找了一些mp3转mid的网站我们没使用过不担保效果。
[https://www.serocs.cn/transcription/](https://www.serocs.cn/transcription/)
同时midishow论坛里有一些大佬也提供了解决方案看看他们的发言也是一个不错的选择。
我就只给个论坛链接了,经常有人问这种问题,你可以去那里随便找到一篇帖子看看。
[论坛](https://www.midishow.com/question)
### 2.4 输出格式的问题
在前面说到,输出主要有`.mcpack``.bdx`文件的输出,接下来我会围绕这两个文件进行简单的说明。
#### 2.4.1 .mcpack是什么
输出.mcpack文件其实对于一个**资深基岩版我的世界玩家**应该并不陌生。
.mcpack文件其实就是我的世界基岩版的附加包里面一般分为行为包和材质包
我们生成的命令组属于**行为包** (下图就是一个例子)
<img src="https://foruda.gitee.com/images/1672647779755793187/884abaa9_10062986.png">
如果你是国际电脑版基岩玩家就像我一样,是可以直接打开这个文件,并将这个包导入我的世界的。
关于怎么使用,请看[**这里**](https://gitee.com/EillesWan/Musicreater/blob/pkgver/docs/%E7%94%9F%E6%88%90%E6%96%87%E4%BB%B6%E7%9A%84%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md)。
#### 2.4.2 .bdx是什么
.bdx 文件其实是FastBuilder这款软件的结构文件可以导入到我的世界。
由于这不属于官方文件且我并不是很熟悉这个结构所以请对这个格式有问题的好兄弟加一下QQ群问问群里负责导入的大佬。
## 第三部分 关于其他问题
**由于开发者们都很忙,群友们的耐心也都有限,所以恳请大家提出有意义的问题。这里附一个关于提问方法的链接,大家可以看看。**
[提问的智慧](https://github.com/tvvocold/How-To-Ask-Questions-The-Smart-Way)
希望不要我把这个文件在聊天中甩给你,那说明我可能已经没有耐心了。
看完这份说明,如果你打算开始使用我们的工具的话,请移步至[这里](https://gitee.com/EillesWan/Musicreater/blob/pkgver/docs/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md)。
## 结尾
### 作者\<*金羿*\>(Eilles)联系方式
1. QQ 2647547478
2. 电邮 EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
3. 微信 WYI_DoctorYI
4. Telegram [@EillesWan](https://t.me/EillesWan)
### 作者\<*诸葛亮与八卦阵*\>(bgArray)联系方式
1. QQ 4740437765
**欢迎加群:[861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr)**
**欢迎加群:[861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr)**
**欢迎加群:[861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr)**
(重要的事情说三遍)
**(有能力的同志麻烦给仓库star一下)**
**(有能力的同志麻烦给仓库star一下)**
**(有能力的同志麻烦给仓库star一下)**

View File

@@ -0,0 +1,32 @@
<h1 align="center">音·创 Musicreater</h1>
<h2 align="center">库版 Package Version</h2>
<p align="center">
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
</p>
# 生成文件的使用说明
*由于先前的 **读我文件**(README.md) 过于冗杂,现另辟蹊径来给大家全方位的教程。*
*这是本库生成后文件的相关说明,不是使用本库的教程,若要查看**本库的演示程序**使用教程,可点击[此处](%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md)*
## 文件格式
1. 附加包格式(`.mcpack`
使用附加包格式导出音乐,则音乐会以指令函数文件(`.mcfunction`)存储于附加包内。在附加包中,函数文件的存储结构应为:
- `functions\`
- `index.mcfunction`
- `mscply\`
- `progressShow.mcfunction`
- `track1.mcfunction`
- `track2.mcfunction`
- ...
- `trackN.mcfunction`
如图,其中,`index.mcfunction`文件和`mscply`文件夹存在于函数目录的根下;在`mscply`目录中,包含音乐导出的众多音轨播放文件(`trackX.mcfunction`),同时,若生成此包时选择了带有进度条的选项,则会包含`progressShow.mcfunction`文件。
`index.mcfunction`用于开始播放,其中包含打开各个音轨对应函数的指令,以及加分指令,这里的加分,是将**播放计分板的值大于等于`1`**的所有**玩家**的播放计分板分数增加`1`。同时,若生成此包时选择了自动重置计分板的选项,则会包含一条重置计分板的指令。

18
example_convert_bdx.py Normal file
View File

@@ -0,0 +1,18 @@
# THIS PROGRAM IS ONLY A TEST EXAMPLE
from msctPkgver.main import *
convertion = midiConvert()
convertion.convert(input('请输入midi文件路径'), input('请输入输出路径:'))
for i in convertion.toBDXfile(
1,
input('请输入作者:'),
bool(int(input('是否开启进度条(1|0)'))),
int(input('请输入指令结构最大生成高度:')),
input('请输入计分板名称:'),
float(input('请输入音量(0-1]')),
float(input('请输入速度倍率:')),
bool(int(input('是否自动重置计分板(1|0)'))),
):
print(i)

View File

@@ -0,0 +1,24 @@
# THIS PROGRAM IS ONLY A TEST EXAMPLE
from msctPkgver.main import *
convertion = midiConvert()
convertion.convert(input("请输入midi文件路径"), input("请输入输出路径:"))
print(
convertion.tomcpack(
3,
bool(int(input("是否自动重置计分板(1|0)"))),
bool(int(input("是否开启进度条(1|0)"))),
input("请输入计分板名称:"),
float(input("请输入音量0-1")),
float(input("请输入速度倍率:")),
)
)
# for the test
# if __name__ == '__main__':
# convertion = midiConvert()
# convertion.convert(r"C:\Users\lc\Documents\MuseScore3\乐谱\乐谱\victory.mid", ".")
# convertion.tomcpack(
# 1, True, True, "scb", 1, 1)

22
example_convert_mcpack.py Normal file
View File

@@ -0,0 +1,22 @@
# THIS PROGRAM IS ONLY A TEST EXAMPLE
from msctPkgver.main import *
convertion = midiConvert()
convertion.convert(input('请输入midi文件路径'), input('请输入输出路径:'))
convertion.tomcpack(
1,
bool(int(input('是否自动重置计分板(1|0)'))),
bool(int(input('是否开启进度条(1|0)'))),
input('请输入计分板名称:'),
float(input('请输入音量0-1')),
float(input('请输入速度倍率:')),
)
# for the test
# if __name__ == '__main__':
# convertion = midiConvert()
# convertion.convert(r"C:\Users\lc\Documents\MuseScore3\乐谱\乐谱\victory.mid", ".")
# convertion.tomcpack(
# 1, True, True, "scb", 1, 1)

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

343
magicDemo.py Normal file
View File

@@ -0,0 +1,343 @@
# -*- coding: utf-8 -*-
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
# 若需转载或借鉴 许可声明请查看仓库目录下的 Lisence.md
"""
音·创 库版 MIDI转换示例程序
Musicreater Package Version : Demo for Midi Conversion
Copyright 2023 all the developers of Musicreater
开源相关声明请见 ./Lisence.md
Terms & Conditions: ./Lisence.md
"""
languages = {
"ZH_CN": {
"MSCT": "音·创",
"ChooseLang": "选择语言",
"LangChd": "当前语言已经切换为",
"ZH_CN": "简体中文",
"ZH_TW": "繁体中文(台湾)",
"EN_GB": "英语(英国)",
"EN_US": "英语(美国)",
":": "",
",": "",
".": "",
"ChooseFileFormat": "请输入输出格式[BDX(1)或MCPACK(0)]",
"ChoosePlayer": "请选择播放方式[计分板(1) 或 延迟(0)]",
"ChoosePath": "请输入MIDI路径或所在文件夹",
"WhetherArgEntering": "是否为文件夹内文件的转换统一参数[是(1) 或 否(0)]",
"EnterArgs": "请输入转换参数",
"noteofArgs": "文件夹内的全部midi将统一以此参数转换",
"ChooseSbReset": "是否自动重置计分板[是(1) 或 否(0)]",
"WhetherCstmProgressBar": "是否自定义进度条[是(1) 或 否(0)]",
"EnterProgressBarStyle": "请输入进度条样式",
"EnterSbName": "请输入计分板名称",
"EnterVolume": "请输入音量大小(0~1)",
"EnterSpeed": "请输入速度倍率",
"EnterAuthor": "请输入作者",
"EnterMaxHeight": "请输入指令结构最大生成高度",
"ErrEnter": "输入错误",
"Re-Enter": "请重新输入",
"Dealing": "正在处理",
"FileNotFound": "文件(夹)不存在",
"ChooseOutPath": "请输入结果输出路径",
"EnterSelecter": "请输入播放者选择器",
"Saying": "言·论",
}
}
import sys
if sys.argv.__len__() > 0:
currentLang = sys.argv[0]
if not currentLang in languages.keys():
currentLang = "ZH_CN"
else:
currentLang = "ZH_CN"
def _(__):
'''
`languages`
'''
return languages[currentLang][__]
import os
import random
import datetime
from msctPkgver.main import *
try:
from rich.console import Console
except ModuleNotFoundError as E:
if input("您需要安装 Rich 模块才能使用这个样例\n请问是否安装?(y/n)").lower() in ('y', '1'):
os.system("pip install Rich -i https://mirrors.aliyun.com/pypi/")
from rich.console import Console
else:
raise E
try:
import zhdate
except ModuleNotFoundError as E:
if input("您需要安装 zhdate 模块才能使用这个样例\n请问是否安装?(y/n)").lower() in ('y', '1'):
os.system("pip install zhdate -i https://mirrors.aliyun.com/pypi/")
import zhdate
else:
raise E
try:
import requests
except ModuleNotFoundError as E:
if input("您需要安装 requests 模块才能使用这个样例\n请问是否安装?(y/n)").lower() in ('y', '1'):
os.system("pip install requests -i https://mirrors.aliyun.com/pypi/")
import requests
else:
raise E
MainConsole = Console()
MainConsole.print(
"[#121110 on #F0F2F4] ",
style="#121110 on #F0F2F4",
justify="center",
)
# 显示大标题
MainConsole.rule(title="[bold #AB70FF]欢迎使用音·创独立转换器", characters="=", style="#26E2FF")
MainConsole.rule(
title="[bold #AB70FF]Welcome to Independent Musicreater Convernter", characters="-"
)
# 显示箴言部分
MainConsole.print(
"[#121110 on #F0F2F4]"
+ random.choice(
requests.get(
"https://gitee.com/EillesWan/Musicreater/raw/master/resources/myWords.txt"
)
.text.strip("\r\n")
.split("\r\n")
),
style="#121110 on #F0F2F4",
justify="center",
)
from typing import Any, Literal, Optional, TextIO
JustifyMethod = Literal["default", "left", "center", "right", "full"]
OverflowMethod = Literal["fold", "crop", "ellipsis", "ignore"]
# 高级的打印函数
def prt(
*objects: Any,
sep: str = " ",
end: str = "\n",
justify: Optional[JustifyMethod] = None,
overflow: Optional[OverflowMethod] = None,
no_wrap: Optional[bool] = None,
emoji: Optional[bool] = None,
markup: Optional[bool] = None,
highlight: Optional[bool] = None,
width: Optional[int] = None,
height: Optional[int] = None,
crop: bool = True,
soft_wrap: Optional[bool] = None,
new_line_start: bool = False,
) -> None:
"""打印到控制台。
Args:
objects (位置性的args): 要记录到终端的对象。
sep (str, 可选): 要在打印数据之间写入的字符串。默认为""
end (str, optio可选nal): 在打印数据结束时写入的字符串。默认值为"\\\\n"
style (Union[str, Style], 可选): 应用于输出的样式。默认为`None`。
justify (str, 可选): 校正位置,可为"default", "left", "right", "center""full". 默认为`None`。
overflow (str, 可选): 控制溢出:"ignore"忽略, "crop"裁剪, "fold"折叠, "ellipsis"省略号。默认为`None`。
no_wrap (Optional[bool], 可选): 禁用文字包装。默认为`None`。
emoji (Optional[bool], 可选): 启用表情符号代码,或使用控制台默认的`None`。默认为`None`。
markup (Optional[bool], 可选): 启用标记,或`None`使用控制台默认值。默认为`None`。
highlight (Optional[bool], 可选): 启用自动高亮,或`None`使用控制台默认值。默认为`None`。
width (Optional[int], 可选): 输出的宽度,或`None`自动检测。默认为`None`。
crop (Optional[bool], 可选): 裁剪输出到终端的宽度。默认为`True`。
soft_wrap (bool, 可选): 启用软包装模式,禁止文字包装和裁剪,或`None``用于 控制台默认值。默认为`None`。
new_line_start (bool, False): 如果输出包含多行,在开始时插入一个新行。默认值为`False`。
"""
MainConsole.print(
*objects,
sep=sep,
end=end,
style="#F0F2F4 on #121110",
justify=justify,
overflow=overflow,
no_wrap=no_wrap,
emoji=emoji,
markup=markup,
highlight=highlight,
width=width,
height=height,
crop=crop,
soft_wrap=soft_wrap,
new_line_start=new_line_start,
)
prt(f"{_('LangChd')}{_(':')}{_(currentLang)}")
# 高级的输入函数
def ipt(
*objects: Any,
sep: str = " ",
justify: Optional[JustifyMethod] = None,
overflow: Optional[OverflowMethod] = None,
no_wrap: Optional[bool] = None,
emoji: Optional[bool] = None,
markup: Optional[bool] = None,
highlight: Optional[bool] = None,
width: Optional[int] = None,
height: Optional[int] = None,
crop: bool = True,
soft_wrap: Optional[bool] = None,
new_line_start: bool = False,
password: bool = False,
stream: Optional[TextIO] = None,
) -> str:
"""显示一个提示并等待用户的输入。
它的工作方式与Python内建的 :func:`input` 函数相同如果Python内建的 :mod:`readline` 模块先前已经加载,则提供详细的行编辑和历史功能。
Args:
objects (位置性的args): 要记录到终端的对象。
sep (str, 可选): 要在打印数据之间写入的字符串。默认为""
end (str, optio可选nal): 在打印数据结束时写入的字符串。默认值为"\\\\n"
style (Union[str, Style], 可选): 应用于输出的样式。默认为`None`。
justify (str, 可选): 校正位置,可为"default", "left", "right", "center""full". 默认为`None`。
overflow (str, 可选): 控制溢出:"ignore"忽略, "crop"裁剪, "fold"折叠, "ellipsis"省略号。默认为`None`。
no_wrap (Optional[bool], 可选): 禁用文字包装。默认为`None`。
emoji (Optional[bool], 可选): 启用表情符号代码,或使用控制台默认的`None`。默认为`None`。
markup (Optional[bool], 可选): 启用标记,或`None`使用控制台默认值。默认为`None`。
highlight (Optional[bool], 可选): 启用自动高亮,或`None`使用控制台默认值。默认为`None`。
width (Optional[int], 可选): 输出的宽度,或`None`自动检测。默认为`None`。
crop (Optional[bool], 可选): 裁剪输出到终端的宽度。默认为`True`。
soft_wrap (bool, 可选): 启用软包装模式,禁止文字包装和裁剪,或`None``用于 控制台默认值。默认为`None`。
new_line_start (bool, False): 如果输出包含多行,在开始时插入一个新行。默认值为`False`。
password (bool, 可选): 隐藏已经输入的文案,默认值为`False`。
stream (TextIO, 可选): 可选从文件中读取(而非控制台),默认为 `None`。
Returns:
str: 从stdin读取的字符串
"""
MainConsole.print(
*objects,
sep=sep,
end="",
style="#F0F2F4 on #121110",
justify=justify,
overflow=overflow,
no_wrap=no_wrap,
emoji=emoji,
markup=markup,
highlight=highlight,
width=width,
height=height,
crop=crop,
soft_wrap=soft_wrap,
new_line_start=new_line_start,
)
return MainConsole.input("", password=password, stream=stream)
def formatipt(notice: str, fun, errnote: str = "", *extraArg):
'''循环输入,以某种格式
notice: 输入时的提示
fun: 格式函数
errnote: 输入不符格式时的提示
*extraArg: 对于函数的其他参数'''
while True:
result = ipt(notice)
try:
funresult = fun(result, *extraArg)
break
except:
prt(errnote)
continue
return result, funresult
# 获取midi列表
while True:
midipath = ipt(f"{_('ChoosePath')}{_(':')}").lower()
if os.path.exists(midipath):
if os.path.isfile(midipath):
midis = (midipath,)
elif os.path.isdir(midipath):
midis = tuple(
(
os.path.join(midipath, i)
for i in os.listdir(midipath)
if i.lower().endswith('.mid') or i.lower().endswith('.midi')
)
)
else:
prt(f"{_('ErrEnter')}{_(',')}{_('Re-Enter')}{_('.')}")
continue
else:
prt(f"{_('FileNotFound')}{_(',')}{_('Re-Enter')}{_('.')}")
continue
break
# 获取输出地址
outpath = formatipt(
f"{_('ChooseOutPath')}{_(':')}",
os.path.exists,
f"{_('FileNotFound')}{_(',')}{_('Re-Enter')}{_('.')}",
).lower()
# 选择输出格式
while True:
fileFormat = ipt(f"{_('ChooseFileFormat')}{_(':')}").lower()
if fileFormat in ('0', 'mcpack'):
fileFormat = 0
prt(_("EnterArgs"))
if len(midis) > 1:
prt(_("noteofArgs"))
elif fileFormat in ('1', 'bdx'):
fileFormat = 1
while True:
playerFormat = ipt(f"{_('ChoosePlayer')}{_(':')}").lower()
if playerFormat in ('0', '延迟'):
playerFormat = 0
elif playerFormat in ('1', '计分板'):
playerFormat = 1
else:
prt(f"{_('ErrEnter')}{_(',')}{_('Re-Enter')}{_('.')}")
continue
break
else:
prt(f"{_('ErrEnter')}{_(',')}{_('Re-Enter')}{_('.')}")
continue
break
if fileFormat == 0:
pass
MainConsole.input()

67
magicFun.py Normal file
View File

@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
# 若需转载或借鉴 请依照 Apache 2.0 许可证进行许可
"""
音·创 库版 MIDI转换示例程序
Musicreater Package Version : Demo for Midi Conversion
Copyright 2022 all the developers of Musicreater
Licensed under the Apache License, Version 2.0 (the 'License');
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an 'AS IS' BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from rich.console import Console
MainConsole = Console()
import requests
import random
# 欸嘿!
while True:
MainConsole.print(
"[#121110 on #F0F2F4] ",
style="#121110 on #F0F2F4",
justify="center",
)
MainConsole.rule(title="[bold #AB70FF]欢迎使用音·创独立转换器", characters="=", style="#26E2FF")
MainConsole.rule(
title="[bold #AB70FF]Welcome to Independent Musicreater Convernter", characters="-"
)
MainConsole.print(
"[#121110 on #F0F2F4]"
+ random.choice(
requests.get(
"https://gitee.com/EillesWan/Musicreater/raw/master/resources/myWords.txt"
)
.text.strip("\r\n")
.split("\r\n")
),
style="#121110 on #F0F2F4",
justify="center",
)
MainConsole.print()

153
mid_analyse.py Normal file
View File

@@ -0,0 +1,153 @@
# -*- coding: utf-8 -*-
##########################################################################
# Form generated from reading UI file 'mid_analyse.ui'
##
# Created by: Qt User Interface Compiler version 6.4.1
##
# WARNING! All changes made in this file will be lost when recompiling UI file!
##########################################################################
# from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
# QMetaObject, QObject, QPoint, QRect,
# QSize, QTime, QUrl, Qt)
# from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
# QFont, QFontDatabase, QGradient, QIcon,
# QImage, QKeySequence, QLinearGradient, QPainter,
# QPalette, QPixmap, QRadialGradient, QTransform)
# from PySide6.QtWidgets import (QApplication, QGroupBox, QHBoxLayout, QLabel,
# QLineEdit, QPushButton, QSizePolicy, QWidget)
import sys
from PySide6.QtWidgets import QApplication, QWidget, QGroupBox, QPushButton, \
QLabel, QLineEdit, QHBoxLayout, QFileDialog
from PySide6.QtCore import QRect, QMetaObject, Slot
class Ui_Form(QWidget):
def __init__(self):
super().__init__()
self.groupBox = None
self.horizontalLayout = None
self.horizontalLayoutWidget = None
self.close_button = None
self.fileChoseButton = None
self.input_button = None
self.note_count_label = None
self.note_count_shower = None
self.output_button = None
def setupUi(self, Form):
if not Form.objectName():
Form.setObjectName(u"Form")
Form.resize(582, 355)
self.groupBox = QGroupBox(Form)
self.groupBox.setObjectName(u"groupBox")
self.groupBox.setGeometry(QRect(10, 0, 561, 311))
self.fileChoseButton = QPushButton(self.groupBox)
self.fileChoseButton.setObjectName(u"file_chose_button")
self.fileChoseButton.setGeometry(QRect(10, 20, 75, 24))
self.note_count_label = QLabel(self.groupBox)
self.note_count_label.setObjectName(u"note_count_label")
self.note_count_label.setGeometry(QRect(20, 50, 54, 16))
self.note_count_shower = QLineEdit(self.groupBox)
self.note_count_shower.setObjectName(u"note_count_shower")
self.note_count_shower.setGeometry(QRect(70, 50, 113, 20))
self.horizontalLayoutWidget = QWidget(Form)
self.horizontalLayoutWidget.setObjectName(u"horizontalLayoutWidget")
self.horizontalLayoutWidget.setGeometry(QRect(10, 310, 561, 41))
self.horizontalLayout = QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.input_button = QPushButton(self.horizontalLayoutWidget)
self.input_button.setObjectName(u"input_button")
self.horizontalLayout.addWidget(self.input_button)
self.output_button = QPushButton(self.horizontalLayoutWidget)
self.output_button.setObjectName(u"output_button")
self.horizontalLayout.addWidget(self.output_button)
self.close_button = QPushButton(self.horizontalLayoutWidget)
self.close_button.setObjectName(u"close_button")
self.horizontalLayout.addWidget(self.close_button)
Form.setWindowTitle("Mid解析器")
self.groupBox.setTitle("mid信息")
self.fileChoseButton.setText("选择文件")
self.note_count_label.setText("音符数")
self.input_button.setText("导入")
self.output_button.setText("导出分析")
self.close_button.setText("关闭")
QMetaObject.connectSlotsByName(Form)
# self.ui.btnCalculate.clicked.connect(self.fileLoading)
def fileLoading(self):
filePath, _ = QFileDialog.getOpenFileName(
self.groupBox, # 父窗口对象
"选择文件", # 标题
r"./", # 起始目录
"mid类型 (*.mid *.midi)" # 选择类型过滤项,过滤内容在括号中
)
print(filePath)
@Slot()
def on_fileChoseButton_clicked(self):
filePath, _ = QFileDialog.getOpenFileName(
self.groupBox, # 父窗口对象
"选择文件", # 标题
r"./", # 起始目录
"mid类型 (*.mid *.midi)" # 选择类型过滤项,过滤内容在括号中
)
print(filePath)
class MidAnalyseGui(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.ui.fileChoseButton.clicked.connect(self.fileLoading)
def fileLoading(self):
filePath, _ = QFileDialog.getOpenFileName(
self.ui.groupBox, # 父窗口对象
"选择文件", # 标题
r"./", # 起始目录
"mid类型 (*.mid *.midi)" # 选择类型过滤项,过滤内容在括号中
)
print(filePath)
@Slot()
def on_fileChoseButton_clicked(self):
filePath, _ = QFileDialog.getOpenFileName(
self.ui.groupBox, # 父窗口对象
"选择文件", # 标题
r"./", # 起始目录
"mid类型 (*.mid *.midi)" # 选择类型过滤项,过滤内容在括号中
)
print(filePath)
if __name__ == "__main__":
app = QApplication(sys.argv) # 创建一个QApplication也就是你要开发的软件app
# MainWindow = QMainWindow() # 创建一个QMainWindow用来装载你需要的各种组件、控件
# MainWindow = QWidget() # 创建一个QMainWindow用来装载你需要的各种组件、控件
ui = MidAnalyseGui() # ui是你创建的ui类的实例化对象
# ui.setupUi(MainWindow) # 执行类中的setupUi方法方法的参数是第二步中创建的QMainWindow
ui.show() # 执行QMainWindow的show()方法显示这个QMainWindow
sys.exit(app.exec()) # 使用exit()或者点击关闭按钮退出QApplication
if __name__ == '__main__':
app = QApplication(sys.argv)
MainWindow = QWidget()
ui = Ui_Form()
ui.setupUi(MainWindow)
ui.show()
sys.exit(app.exec())

101
mid_analyse.ui Normal file
View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>582</width>
<height>355</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>10</x>
<y>0</y>
<width>561</width>
<height>311</height>
</rect>
</property>
<property name="title">
<string>mid信息</string>
</property>
<widget class="QPushButton" name="file_chose_button">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>75</width>
<height>24</height>
</rect>
</property>
<property name="text">
<string>选择文件</string>
</property>
</widget>
<widget class="QLabel" name="note_count_label">
<property name="geometry">
<rect>
<x>20</x>
<y>50</y>
<width>54</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>音符数</string>
</property>
</widget>
<widget class="QLineEdit" name="note_count_shower">
<property name="geometry">
<rect>
<x>70</x>
<y>50</y>
<width>113</width>
<height>20</height>
</rect>
</property>
</widget>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>310</y>
<width>561</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="input_button">
<property name="text">
<string>导入</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="output_button">
<property name="text">
<string>导出分析</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="close_button">
<property name="text">
<string>关闭</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

34
msctPkgver/__init__.py Normal file
View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
"""一个简单的基于音·创的我的世界音频操作工具"""
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
# 若需转载或借鉴 许可声明请查看仓库目录下的 Lisence.md
__version__ = '0.1.0'
__all__ = []
__author__ = (('金羿', 'Eilles Wan'), ('诸葛亮与八卦阵', 'bgArray'), ('鸣凤鸽子', 'MingFengPigeon'))
"""
音·创 库版 (Musicreater Package Version)
是一款免费开源的针对《我的世界基岩版》的midi音乐转换库
Musicreater pkgver (Package Version 音·创 库版)
A free open source library used for convert midi file into formats that is suitable for **Minecraft: Bedrock Edition**.
Copyright 2023 all the developers of Musicreater
开源相关声明请见 ../Lisence.md
Terms & Conditions: ../Lisence.md
"""
from .main import *
print('此Midi转换功能由音·创开发者开发版权归参与开发的人员共同所有。')
print('Copyright © 2022 all the developers of Musicreater')
print("小贴不妨试试Mid-BDX转换网页在线的多功能Midi转换器")
print("https://dislink.github.io/midi2bdx/")

60
msctPkgver/exceptions.py Normal file
View File

@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
# 若需转载或借鉴 许可声明请查看仓库目录下的 Lisence.md
"""
音·创 库版 (Musicreater Package Version)
是一款免费开源的针对《我的世界基岩版》的midi音乐转换库
Musicreater pkgver (Package Version 音·创 库版)
A free open source library used for convert midi file into formats that is suitable for **Minecraft: Bedrock Edition**.
Copyright 2023 all the developers of Musicreater
开源相关声明请见 ../Lisence.md
Terms & Conditions: ../Lisence.md
"""
class MSCTBaseException(Exception):
"""音·创库版本的所有错误均继承于此"""
def __init__(self, *args):
super().__init__(*args)
def (self,):
for i in self.args:
print(i+"喵!")
def crash_it(self):
raise self
class CrossNoteError(MSCTBaseException):
'''同通道下同音符交叉出现所产生的错误'''
pass
class NotDefineTempoError(MSCTBaseException):
'''没有Tempo设定导致时间无法计算的错误'''
pass
class MidiDestroyedError(MSCTBaseException):
'''Midi文件损坏'''
pass
class ChannelOverFlowError(MSCTBaseException):
'''一个midi中含有过多的通道数量应≤16'''
pass
class NotDefineProgramError(MSCTBaseException):
'''没有Program设定导致没有乐器可以选择的错误'''
pass

217
msctPkgver/magicmain.py Normal file
View File

@@ -0,0 +1,217 @@
# -*- coding: utf-8 -*-
# 音·创 开发交流群 861684859
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
# 若需使用或借鉴 请依照 Apache 2.0 许可证进行许可
"""
音·创 库版 (Musicreater Package Version)
是一款免费开源的针对《我的世界基岩版》的midi音乐转换库
注意除了此源文件以外任何属于此仓库以及此项目的文件均依照Apache许可证进行许可
Musicreater pkgver (Package Version 音·创 库版)
A free open source library used for convert midi file into formats that is suitable for **Minecraft: Bedrock Edition**.
Note! Except for this source file, all the files in this repository and this project are licensed under Apache License 2.0
Copyright 2022 all the developers of Musicreater
Licensed under the Apache License, Version 2.0 (the 'License');
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an 'AS IS' BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
def _toCmdList_m1(
self,
scoreboardname: str = "mscplay",
volume: float = 1.0,
speed: float = 1.0) -> list:
"""
使用Dislink Sforza的转换思路将midi转换为我的世界命令列表
:param scoreboardname: 我的世界的计分板名称
:param volume: 音量,注意:这里的音量范围为(0,1],如果超出将被处理为正确值,其原理为在距离玩家 (1 / volume -1) 的地方播放音频
:param speed: 速度,注意:这里的速度指的是播放倍率,其原理为在播放音频的时候,每个音符的播放时间除以 speed
:return: tuple(命令列表, 命令个数, 计分板最大值)
"""
tracks = []
if volume > 1:
volume = 1
if volume <= 0:
volume = 0.001
commands = 0
maxscore = 0
for i, track in enumerate(self.midi.tracks):
ticks = 0
instrumentID = 0
singleTrack = []
for msg in track:
ticks += msg.time
# print(msg)
if msg.is_meta:
if msg.type == "set_tempo":
tempo = msg.tempo
else:
if msg.type == "program_change":
# print("TT")
instrumentID = msg.program
if msg.type == "note_on" and msg.velocity != 0:
nowscore = round(
(ticks * tempo)
/ ((self.midi.ticks_per_beat * float(speed)) * 50000)
)
maxscore = max(maxscore, nowscore)
soundID, _X = self.__Inst2soundIDwithX(instrumentID)
singleTrack.append(
"execute @a[scores={" +
str(scoreboardname) +
"=" +
str(nowscore) +
"}" +
f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}")
commands += 1
if len(singleTrack) != 0:
tracks.append(singleTrack)
return [tracks, commands, maxscore]
# ============================
import mido
class NoteMessage:
def __init__(self, channel, pitch, velocity, startT, lastT, midi, now_bpm, change_bpm=None):
self.channel = channel
self.note = pitch
self.velocity = velocity
self.startTime = startT
self.lastTime = lastT
self.tempo = now_bpm # 这里要程序实现获取bpm可以参考我的程序
def mt2gt(mt, tpb_a, bpm_a):
return mt / tpb_a / bpm_a * 60
self.startTrueTime = mt2gt(self.startTime, midi.ticks_per_beat, self.tempo) # / 20
# delete_extra_zero(round_up())
if change_bpm is not None:
self.lastTrueTime = mt2gt(self.lastTime, midi.ticks_per_beat, change_bpm) # / 20
else:
self.lastTrueTime = mt2gt(self.lastTime, midi.ticks_per_beat, self.tempo) # / 20
# delete_extra_zero(round_up())
print((self.startTime * self.tempo) / (midi.ticks_per_beat * 50000))
def __str__(self):
return "noteMessage channel=" + str(self.channel) + " note=" + str(self.note) + " velocity=" + \
str(self.velocity) + " startTime=" + str(self.startTime) + " lastTime=" + str(self.lastTime) + \
" startTrueTime=" + str(self.startTrueTime) + " lastTrueTime=" + str(self.lastTrueTime)
def load(mid: mido.MidiFile):
type_ = [False, False, False] # note_off / note_on+0 / mixed
is_tempo = False
# 预检
for i, track in enumerate(mid.tracks):
for msg in track:
# print(msg)
if msg.is_meta is not True:
if msg.type == 'note_on' and msg.velocity == 0:
type_[1] = True
elif msg.type == "note_off":
type_[0] = True
if msg.is_meta is True and msg.type == "set_tempo":
is_tempo = True
if is_tempo is not True:
raise Exception("这个mid没有可供计算时间的tempo事件")
if type_[0] is True and type_[1] is True:
type_[2] = True
type_[1] = False
type_[0] = False
print(type_)
bpm = 0
recent_change_bpm = 0
is_change_bpm = False
# 实检
for i, track in enumerate(mid.tracks):
noteOn = []
trackS = []
ticks = 0
for msg in track:
print(msg)
ticks += msg.time
print(ticks)
if msg.is_meta is True and msg.type == "set_tempo":
recent_change_bpm = bpm
bpm = 60000000 / msg.tempo
is_change_bpm = True
if msg.type == 'note_on' and msg.velocity != 0:
noteOn.append([msg, msg.note, ticks])
if type_[1] is True:
if msg.type == 'note_on' and msg.velocity == 0:
for u in noteOn:
index = 0
if u[1] == msg.note:
lastMessage = u[0]
lastTick = u[2]
break
index += 1
print(lastTick)
if is_change_bpm and recent_change_bpm != 0:
trackS.append(NoteMessage(msg.channel, msg.note, lastMessage.velocity, lastTick, ticks - lastTick,
mid, recent_change_bpm, bpm))
is_change_bpm = False
else:
trackS.append(
NoteMessage(msg.channel, msg.note, lastMessage.velocity, lastTick, ticks - lastTick,
mid, bpm))
# print(noteOn)
# print(index)
try:
noteOn.pop(index)
except IndexError:
noteOn.pop(index - 1)
print(trackS)
for j in trackS:
print(j)
if __name__ == '__main__':
load(mido.MidiFile("test.mid"))

1547
msctPkgver/main.py Normal file

File diff suppressed because it is too large Load Diff

47
poem.txt Normal file
View File

@@ -0,0 +1,47 @@
> 是谁把科技的领域布满政治的火药
>
> 是谁把纯净的蓝天染上暗淡的沉灰
>
> 中国人民无不热爱自己伟大的祖国
>
> 我们不会忘记屈辱历史留下的惨痛
>
> 我们希望世界和平
>
> 我们希望获得世界的尊重
>
> 愿世上再也没有战争
>
> 无论是热还是冷
>
> 无论是经济还是政治
>
> 让美妙的和平的优雅的音乐响彻世界
>
> ——金羿
> 2022 5 7
> Who has dropped political gunpowder into the technology
>
> Who has dyed clear blue sky into the dark grey
>
> All Chinese people love our great homeland
>
> We *WILL* remember the remain pain of the humiliating history
>
> We love the whole world but in peace
>
> We love everyone but under respect
>
> It is to be hoped that the war ends forever
>
> Whatever it is cold or hot
>
> Whatever it is economical or political
>
> Just let the wonderful music of peace surround the world
>
> ---- Eilles Wan
> 7/5 2022

580
pp.py Normal file
View File

@@ -0,0 +1,580 @@
# -*- coding: utf-8 -*-
##########################################################################
# Form generated from reading UI file 'PySide6-Pkg.ui'
##
# Created by: Qt User Interface Compiler version 6.4.1
##
# WARNING! All changes made in this file will be lost when recompiling UI file!
##########################################################################
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
QCursor, QFont, QFontDatabase, QGradient,
QIcon, QImage, QKeySequence, QLinearGradient,
QPainter, QPalette, QPixmap, QRadialGradient,
QTransform)
from PySide6.QtWidgets import (
QApplication,
QCheckBox,
QComboBox,
QHBoxLayout,
QHeaderView,
QLabel,
QMainWindow,
QMenu,
QMenuBar,
QSizePolicy,
QSlider,
QSpinBox,
QStatusBar,
QTabWidget,
QTableWidget,
QTableWidgetItem,
QTextEdit,
QToolButton,
QVBoxLayout,
QWidget)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
MainWindow.resize(800, 600)
self.action = QAction(MainWindow)
self.action.setObjectName(u"action")
icon = QIcon()
iconThemeName = u"document-open"
if QIcon.hasThemeIcon(iconThemeName):
icon = QIcon.fromTheme(iconThemeName)
else:
icon.addFile(u".", QSize(), QIcon.Normal, QIcon.Off)
self.action.setIcon(icon)
self.action_Input = QAction(MainWindow)
self.action_Input.setObjectName(u"action_Input")
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.verticalLayoutWidget = QWidget(self.centralwidget)
self.verticalLayoutWidget.setObjectName(u"verticalLayoutWidget")
self.verticalLayoutWidget.setGeometry(QRect(0, 0, 951, 611))
self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setObjectName(u"verticalLayout")
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.tabO = QTabWidget(self.verticalLayoutWidget)
self.tabO.setObjectName(u"tabO")
self.tab = QWidget()
self.tab.setObjectName(u"tab")
self.verticalLayoutWidget_2 = QWidget(self.tab)
self.verticalLayoutWidget_2.setObjectName(u"verticalLayoutWidget_2")
self.verticalLayoutWidget_2.setGeometry(QRect(0, 0, 881, 591))
self.verticalLayout_2 = QVBoxLayout(self.verticalLayoutWidget_2)
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.tableWidget = QTableWidget(self.verticalLayoutWidget_2)
self.tableWidget.setObjectName(u"tableWidget")
self.verticalLayout_2.addWidget(self.tableWidget)
self.tabO.addTab(self.tab, "")
self.tab_2 = QWidget()
self.tab_2.setObjectName(u"tab_2")
self.label = QLabel(self.tab_2)
self.label.setObjectName(u"label")
self.label.setGeometry(QRect(10, 10, 71, 16))
self.widget = QWidget(self.tab_2)
self.widget.setObjectName(u"widget")
self.widget.setGeometry(QRect(0, 30, 281, 131))
self.verticalLayoutWidget_3 = QWidget(self.widget)
self.verticalLayoutWidget_3.setObjectName(u"verticalLayoutWidget_3")
self.verticalLayoutWidget_3.setGeometry(QRect(10, 0, 271, 131))
self.verticalLayout_3 = QVBoxLayout(self.verticalLayoutWidget_3)
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
self.label_2 = QLabel(self.verticalLayoutWidget_3)
self.label_2.setObjectName(u"label_2")
self.verticalLayout_3.addWidget(self.label_2)
self.label_4 = QLabel(self.verticalLayoutWidget_3)
self.label_4.setObjectName(u"label_4")
self.verticalLayout_3.addWidget(self.label_4)
self.label_5 = QLabel(self.verticalLayoutWidget_3)
self.label_5.setObjectName(u"label_5")
self.verticalLayout_3.addWidget(self.label_5)
self.label_7 = QLabel(self.verticalLayoutWidget_3)
self.label_7.setObjectName(u"label_7")
self.verticalLayout_3.addWidget(self.label_7)
self.label_6 = QLabel(self.verticalLayoutWidget_3)
self.label_6.setObjectName(u"label_6")
self.verticalLayout_3.addWidget(self.label_6)
self.label_3 = QLabel(self.verticalLayoutWidget_3)
self.label_3.setObjectName(u"label_3")
self.verticalLayout_3.addWidget(self.label_3)
self.widget_2 = QWidget(self.tab_2)
self.widget_2.setObjectName(u"widget_2")
self.widget_2.setGeometry(QRect(280, 30, 281, 131))
self.verticalLayoutWidget_4 = QWidget(self.widget_2)
self.verticalLayoutWidget_4.setObjectName(u"verticalLayoutWidget_4")
self.verticalLayoutWidget_4.setGeometry(QRect(10, 0, 271, 131))
self.verticalLayout_4 = QVBoxLayout(self.verticalLayoutWidget_4)
self.verticalLayout_4.setObjectName(u"verticalLayout_4")
self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
self.label_9 = QLabel(self.verticalLayoutWidget_4)
self.label_9.setObjectName(u"label_9")
self.verticalLayout_4.addWidget(self.label_9)
self.label_8 = QLabel(self.verticalLayoutWidget_4)
self.label_8.setObjectName(u"label_8")
self.verticalLayout_4.addWidget(self.label_8)
self.label_10 = QLabel(self.verticalLayoutWidget_4)
self.label_10.setObjectName(u"label_10")
self.verticalLayout_4.addWidget(self.label_10)
self.label_12 = QLabel(self.verticalLayoutWidget_4)
self.label_12.setObjectName(u"label_12")
self.verticalLayout_4.addWidget(self.label_12)
self.label_13 = QLabel(self.verticalLayoutWidget_4)
self.label_13.setObjectName(u"label_13")
self.verticalLayout_4.addWidget(self.label_13)
self.label_11 = QLabel(self.verticalLayoutWidget_4)
self.label_11.setObjectName(u"label_11")
self.verticalLayout_4.addWidget(self.label_11)
self.widget_3 = QWidget(self.tab_2)
self.widget_3.setObjectName(u"widget_3")
self.widget_3.setGeometry(QRect(10, 160, 781, 191))
self.verticalLayoutWidget_5 = QWidget(self.widget_3)
self.verticalLayoutWidget_5.setObjectName(u"verticalLayoutWidget_5")
self.verticalLayoutWidget_5.setGeometry(QRect(0, 0, 781, 191))
self.verticalLayout_5 = QVBoxLayout(self.verticalLayoutWidget_5)
self.verticalLayout_5.setObjectName(u"verticalLayout_5")
self.verticalLayout_5.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.label_14 = QLabel(self.verticalLayoutWidget_5)
self.label_14.setObjectName(u"label_14")
self.horizontalLayout.addWidget(self.label_14)
self.comboBox = QComboBox(self.verticalLayoutWidget_5)
self.comboBox.setObjectName(u"comboBox")
self.horizontalLayout.addWidget(self.comboBox)
self.toolButton = QToolButton(self.verticalLayoutWidget_5)
self.toolButton.setObjectName(u"toolButton")
self.horizontalLayout.addWidget(self.toolButton)
self.verticalLayout_5.addLayout(self.horizontalLayout)
self.horizontalLayout_5 = QHBoxLayout()
self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
self.horizontalLayout_4 = QHBoxLayout()
self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
self.horizontalLayout_2 = QHBoxLayout()
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.label_15 = QLabel(self.verticalLayoutWidget_5)
self.label_15.setObjectName(u"label_15")
self.horizontalLayout_2.addWidget(self.label_15)
self.horizontalSlider = QSlider(self.verticalLayoutWidget_5)
self.horizontalSlider.setObjectName(u"horizontalSlider")
self.horizontalSlider.setOrientation(Qt.Horizontal)
self.horizontalLayout_2.addWidget(self.horizontalSlider)
self.horizontalLayout_4.addLayout(self.horizontalLayout_2)
self.label_17 = QLabel(self.verticalLayoutWidget_5)
self.label_17.setObjectName(u"label_17")
self.horizontalLayout_4.addWidget(self.label_17)
self.horizontalSlider_3 = QSlider(self.verticalLayoutWidget_5)
self.horizontalSlider_3.setObjectName(u"horizontalSlider_3")
self.horizontalSlider_3.setOrientation(Qt.Horizontal)
self.horizontalLayout_4.addWidget(self.horizontalSlider_3)
self.horizontalLayout_5.addLayout(self.horizontalLayout_4)
self.horizontalLayout_9 = QHBoxLayout()
self.horizontalLayout_9.setObjectName(u"horizontalLayout_9")
self.label_21 = QLabel(self.verticalLayoutWidget_5)
self.label_21.setObjectName(u"label_21")
self.horizontalLayout_9.addWidget(self.label_21)
self.spinBox = QSpinBox(self.verticalLayoutWidget_5)
self.spinBox.setObjectName(u"spinBox")
self.horizontalLayout_9.addWidget(self.spinBox)
self.horizontalLayout_5.addLayout(self.horizontalLayout_9)
self.verticalLayout_5.addLayout(self.horizontalLayout_5)
self.horizontalLayout_16 = QHBoxLayout()
self.horizontalLayout_16.setObjectName(u"horizontalLayout_16")
self.horizontalLayout_13 = QHBoxLayout()
self.horizontalLayout_13.setObjectName(u"horizontalLayout_13")
self.label_24 = QLabel(self.verticalLayoutWidget_5)
self.label_24.setObjectName(u"label_24")
self.horizontalLayout_13.addWidget(self.label_24)
self.comboBox_3 = QComboBox(self.verticalLayoutWidget_5)
self.comboBox_3.setObjectName(u"comboBox_3")
self.horizontalLayout_13.addWidget(self.comboBox_3)
self.horizontalLayout_6 = QHBoxLayout()
self.horizontalLayout_6.setObjectName(u"horizontalLayout_6")
self.label_18 = QLabel(self.verticalLayoutWidget_5)
self.label_18.setObjectName(u"label_18")
self.horizontalLayout_6.addWidget(self.label_18)
self.textEdit = QTextEdit(self.verticalLayoutWidget_5)
self.textEdit.setObjectName(u"textEdit")
self.textEdit.setMaximumSize(QSize(16777215, 22))
self.horizontalLayout_6.addWidget(self.textEdit)
self.horizontalLayout_8 = QHBoxLayout()
self.horizontalLayout_8.setObjectName(u"horizontalLayout_8")
self.label_20 = QLabel(self.verticalLayoutWidget_5)
self.label_20.setObjectName(u"label_20")
self.label_20.setMaximumSize(QSize(16777215, 22))
self.horizontalLayout_8.addWidget(self.label_20)
self.textEdit_2 = QTextEdit(self.verticalLayoutWidget_5)
self.textEdit_2.setObjectName(u"textEdit_2")
self.textEdit_2.setMaximumSize(QSize(16777215, 22))
self.horizontalLayout_8.addWidget(self.textEdit_2)
self.horizontalLayout_6.addLayout(self.horizontalLayout_8)
self.horizontalLayout_13.addLayout(self.horizontalLayout_6)
self.horizontalLayout_16.addLayout(self.horizontalLayout_13)
self.verticalLayout_5.addLayout(self.horizontalLayout_16)
self.horizontalLayout_7 = QHBoxLayout()
self.horizontalLayout_7.setObjectName(u"horizontalLayout_7")
self.label_19 = QLabel(self.verticalLayoutWidget_5)
self.label_19.setObjectName(u"label_19")
self.label_19.setMaximumSize(QSize(16777215, 22))
self.horizontalLayout_7.addWidget(self.label_19)
self.textEdit1 = QTextEdit(self.verticalLayoutWidget_5)
self.textEdit1.setObjectName(u"textEdit1")
self.textEdit1.setMaximumSize(QSize(16777215, 22))
self.horizontalLayout_7.addWidget(self.textEdit1)
self.horizontalLayout_11 = QHBoxLayout()
self.horizontalLayout_11.setObjectName(u"horizontalLayout_11")
self.checkBox_2 = QCheckBox(self.verticalLayoutWidget_5)
self.checkBox_2.setObjectName(u"checkBox_2")
self.horizontalLayout_11.addWidget(self.checkBox_2)
self.checkBox = QCheckBox(self.verticalLayoutWidget_5)
self.checkBox.setObjectName(u"checkBox")
self.horizontalLayout_11.addWidget(self.checkBox)
self.label_22 = QLabel(self.verticalLayoutWidget_5)
self.label_22.setObjectName(u"label_22")
self.horizontalLayout_11.addWidget(self.label_22)
self.textEdit_3 = QTextEdit(self.verticalLayoutWidget_5)
self.textEdit_3.setObjectName(u"textEdit_3")
self.textEdit_3.setMaximumSize(QSize(16777215, 22))
self.horizontalLayout_11.addWidget(self.textEdit_3)
self.horizontalLayout_7.addLayout(self.horizontalLayout_11)
self.verticalLayout_5.addLayout(self.horizontalLayout_7)
self.horizontalLayout_18 = QHBoxLayout()
self.horizontalLayout_18.setObjectName(u"horizontalLayout_18")
self.verticalLayout_5.addLayout(self.horizontalLayout_18)
self.horizontalLayout_12 = QHBoxLayout()
self.horizontalLayout_12.setObjectName(u"horizontalLayout_12")
self.label_23 = QLabel(self.verticalLayoutWidget_5)
self.label_23.setObjectName(u"label_23")
self.label_23.setMaximumSize(QSize(120, 16777215))
self.horizontalLayout_12.addWidget(self.label_23)
self.comboBox_2 = QComboBox(self.verticalLayoutWidget_5)
self.comboBox_2.setObjectName(u"comboBox_2")
self.comboBox_2.setMaximumSize(QSize(200, 16777215))
self.horizontalLayout_12.addWidget(self.comboBox_2)
self.horizontalLayout_14 = QHBoxLayout()
self.horizontalLayout_14.setObjectName(u"horizontalLayout_14")
self.label_25 = QLabel(self.verticalLayoutWidget_5)
self.label_25.setObjectName(u"label_25")
self.horizontalLayout_14.addWidget(self.label_25)
self.comboBox_4 = QComboBox(self.verticalLayoutWidget_5)
self.comboBox_4.setObjectName(u"comboBox_4")
self.horizontalLayout_14.addWidget(self.comboBox_4)
self.horizontalLayout_12.addLayout(self.horizontalLayout_14)
self.verticalLayout_5.addLayout(self.horizontalLayout_12)
self.horizontalLayout_15 = QHBoxLayout()
self.horizontalLayout_15.setObjectName(u"horizontalLayout_15")
self.label_26 = QLabel(self.verticalLayoutWidget_5)
self.label_26.setObjectName(u"label_26")
self.horizontalLayout_15.addWidget(self.label_26)
self.comboBox_5 = QComboBox(self.verticalLayoutWidget_5)
self.comboBox_5.setObjectName(u"comboBox_5")
self.horizontalLayout_15.addWidget(self.comboBox_5)
self.verticalLayout_5.addLayout(self.horizontalLayout_15)
self.tabO.addTab(self.tab_2, "")
self.tab_3 = QWidget()
self.tab_3.setObjectName(u"tab_3")
self.tabO.addTab(self.tab_3, "")
self.tab_4 = QWidget()
self.tab_4.setObjectName(u"tab_4")
self.tabO.addTab(self.tab_4, "")
self.verticalLayout.addWidget(self.tabO)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(0, 0, 800, 26))
self.menu = QMenu(self.menubar)
self.menu.setObjectName(u"menu")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QStatusBar(MainWindow)
self.statusbar.setObjectName(u"statusbar")
MainWindow.setStatusBar(self.statusbar)
self.menubar.addAction(self.menu.menuAction())
self.menu.addAction(self.action)
self.menu.addAction(self.action_Input)
self.retranslateUi(MainWindow)
self.tabO.setCurrentIndex(1)
QMetaObject.connectSlotsByName(MainWindow)
# setupUi
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(
QCoreApplication.translate(
"MainWindow", u"MainWindow", None))
self.action.setText(
QCoreApplication.translate(
"MainWindow",
u"\u6253\u5f00 Open",
None))
self.action_Input.setText(
QCoreApplication.translate(
"MainWindow",
u"\u5bfc\u5165 Input",
None))
self.tabO.setTabText(
self.tabO.indexOf(
self.tab), QCoreApplication.translate(
"MainWindow", u"Tab 1", None))
self.label.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_2.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_4.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_5.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_7.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_6.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_3.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_9.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_8.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_10.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_12.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_13.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_11.setText(
QCoreApplication.translate(
"MainWindow", u"TextLabel", None))
self.label_14.setText(
QCoreApplication.translate(
"MainWindow",
u"\u9ed8\u8ba4\u4fdd\u5b58\u8def\u5f84\uff1a",
None))
self.toolButton.setText(
QCoreApplication.translate(
"MainWindow", u"...", None))
self.label_15.setText(
QCoreApplication.translate(
"MainWindow",
u"\u901f\u5ea6\u500d\u7387",
None))
self.label_17.setText(
QCoreApplication.translate(
"MainWindow",
u"\u97f3\u91cf\u500d\u7387",
None))
self.label_21.setText(
QCoreApplication.translate(
"MainWindow",
u"\u6700\u5927\u6307\u4ee4\u751f\u6210\u9ad8\u5ea6",
None))
self.label_24.setText(
QCoreApplication.translate(
"MainWindow",
u"\u9009\u62e9\u5668\u6a21\u5f0f",
None))
self.label_18.setText(
QCoreApplication.translate(
"MainWindow",
u"\u8ba1\u5206\u677f\u540d\u79f0",
None))
self.label_20.setText(
QCoreApplication.translate(
"MainWindow",
u"\u73a9\u5bb6\u9009\u62e9\u5668",
None))
self.label_19.setText(
QCoreApplication.translate(
"MainWindow",
u"bdx\u4f5c\u8005\u540d\u79f0",
None))
self.checkBox_2.setText(
QCoreApplication.translate(
"MainWindow",
u"\u662f\u5426\u542f\u7528\u8fdb\u5ea6\u6761",
None))
self.checkBox.setText(
QCoreApplication.translate(
"MainWindow",
u"\u662f\u5426\u81ea\u5b9a\u4e49\u8fdb\u5ea6\u6761",
None))
self.label_22.setText(
QCoreApplication.translate(
"MainWindow",
u"\u81ea\u5b9a\u4e49\u8fdb\u5ea6\u6761\u5185\u5bb9\uff1a",
None))
self.label_23.setText(
QCoreApplication.translate(
"MainWindow",
u"\u9009\u62e9\u547d\u4ee4\u683c\u5f0f\u7248\u672c",
None))
self.label_25.setText(
QCoreApplication.translate(
"MainWindow",
u"\u9009\u62e9\u8f6c\u6362\u7b97\u6cd5\u7248\u672c",
None))
self.label_26.setText(
QCoreApplication.translate(
"MainWindow",
u"\u9009\u62e9\u5bfc\u51fa\u6a21\u5f0f",
None))
self.tabO.setTabText(
self.tabO.indexOf(
self.tab_2), QCoreApplication.translate(
"MainWindow", u"Tab 2", None))
self.tabO.setTabText(
self.tabO.indexOf(
self.tab_3), QCoreApplication.translate(
"MainWindow", u"\u9875", None))
self.tabO.setTabText(
self.tabO.indexOf(
self.tab_4), QCoreApplication.translate(
"MainWindow", u"\u9875", None))
self.menu.setTitle(
QCoreApplication.translate(
"MainWindow",
u"\u6587\u4ef6",
None))
# retranslateUi
# Error: PySide6-Pkg.ui: Warning: The name 'textEdit' (QTextEdit) is already in use, defaulting to 'textEdit1'.
#
#
# while executing
# 'C:\Users\lc\AppData\Roaming\Python\Python39\site-packages\PySide6\uic
# -g python PySide6-Pkg.ui'
if __name__ == "__main__":
import sys
from PySide6 import QtWidgets
app = QtWidgets.QApplication(sys.argv) # 创建一个QApplication也就是你要开发的软件app
MainWindow = QtWidgets.QMainWindow() # 创建一个QMainWindow用来装载你需要的各种组件、控件
# MainWindow = QtWidgets.QWidget() # 创建一个QMainWindow用来装载你需要的各种组件、控件
ui = Ui_MainWindow() # ui是你创建的ui类的实例化对象
ui.setupUi(MainWindow) # 执行类中的setupUi方法方法的参数是第二步中创建的QMainWindow
MainWindow.show() # 执行QMainWindow的show()方法显示这个QMainWindow
sys.exit(app.exec_()) # 使用exit()或者点击关闭按钮退出QApplication

47
pp_main_write.py Normal file
View File

@@ -0,0 +1,47 @@
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QLabel, QPushButton
from PySide6.QtCore import Qt
from PySide6.QtGui import QPixmap
class MusicreaterGUI:
def __init__(self):
self.button, self.label = None, None
def setupUi(self, window):
window.setWindowTitle("音·创") # 窗口标题
window.resize(300, 150) # 重置大小
self.label = QLabel(window) # 在窗口上创建实例化label
string = "welcome to musicreater"
self.label.setText(string)
self.label.setGeometry(80, 50, 150, 20)
self.button = QPushButton(window)
self.button.setText("close")
self.button.setGeometry(120, 100, 50, 20)
self.button.clicked.connect(window.close)
class MusicreaterWidget(QWidget, MusicreaterGUI): # 很棒的继承,请 体会
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv) # 创建应用程序实例对象
app.setApplicationDisplayName("Musicreater-pp")
app.setApplicationVersion("v0.0.1")
app.setEffectEnabled(Qt.UI_AnimateCombo)
app.setWindowIcon(QPixmap(r"logo_done_c_Finish_C_Done_CCC_1024px.ico"))
window_ = MusicreaterWidget() # 窗口实例化
window_.show()
n = app.exec()
print(n)
try:
sys.exit(n)
except SystemExit:
print("hi, error")

View File

@@ -1,49 +0,0 @@
[tool.briefcase]
project_name = "Musicreater"
bundle = "com.ryoun.musicreater"
version = "0.0.1"
url = "https://musicreater.ryoun.com/musicreater"
license = "Apache Software License"
author = 'Eilles Wan'
author_email = "W-YI_DoctorYI@outlook.com"
[tool.briefcase.app.musicreater]
formal_name = "Musicreater"
description = "Musicreater is an Eilles's app that is used for creating musics in Minecraft: Bedrock Edition"
icon = "src/musicreater/resources/musicreater"
sources = ['src/musicreater']
requires = []
[tool.briefcase.app.musicreater.macOS]
requires = [
'toga-cocoa>=0.3.0.dev20',
]
[tool.briefcase.app.musicreater.linux]
requires = [
'toga-gtk>=0.3.0.dev20',
]
system_requires = [
'libgirepository1.0-dev',
'libcairo2-dev',
'libpango1.0-dev',
'libwebkitgtk-3.0-0',
'gir1.2-webkit-3.0',
]
[tool.briefcase.app.musicreater.windows]
requires = [
'toga-winforms>=0.3.0.dev20',
]
# Mobile deployments
[tool.briefcase.app.musicreater.iOS]
requires = [
'toga-iOS>=0.3.0.dev20',
]
[tool.briefcase.app.musicreater.android]
requires = [
'toga-android>=0.3.0.dev20',
]

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
briefcase

View File

@@ -1,10 +0,0 @@
Metadata-Version: 2.1
Briefcase-Version: 0.3.5
Name: musicreater
Formal-Name: Musicreater
App-ID: com.ryoun.musicreater.musicreater
Version: 0.0.1
Home-page: https://musicreater.ryoun.com/musicreater
Author: Eilles Wan
Author-email: W-YI_DoctorYI@outlook.com
Summary: Musicreater is an Eilles's app that is used for creating musics in Minecraft: Bedrock Edition

View File

@@ -1,364 +0,0 @@
# -*- coding: utf-8 -*-
# W-YI 金羿
# QQ 2647547478
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com
# 版权所有 Team-Ryoun 金羿
# 若需转载或借鉴 请附作者
# 代码写的并非十分的漂亮还请大佬多多包涵本软件源代码依照Apache软件协议公开
import json
import os
import shutil
import threading
import sys
from musicreater.msctspt.threadOpera import NewThread
from musicreater.msctspt.bugReporter import version
from musicreater.nmcsup.log import log
__version__ = version.version[1]+version.version[0]
__author__ = 'W-YI (金羿)'
log("系统工作————————加载变量及函数")
print("更新执行位置...")
if sys.platform == 'win32':
os.chdir(__file__[:len(__file__)-__file__[len(__file__)::-1].index('\\')])
log("更新执行位置,当前文件位置"+__file__)
else:
try:
os.chdir(__file__[:len(__file__) -
__file__[len(__file__)::-1].index('/')])
except:
pass
log("其他平台:"+sys.platform+"更新执行位置,当前文件位置"+__file__)
print('完成!')
print('建立变量,存入内存,载入字典常量函数')
# 主体部分
# 支持多文件同时操作
# dataset[{ 'mainset':{ 'x':'y' }, 'musics': [ { 'set' :{ 'A':'B' } , 'note' : [ [ 'a' , b ], ] }, ] }, ]
# 编辑:
# 修改主设置: dataset[第几个项目]['mainset']['什么设置'] = '设置啥'
# 修改音乐: dataset[第几个项目]['musics'][第几个音轨]['notes'][第几个音符][音符还是时间01] = 改成啥
# 修改音轨设置: dataset[第几个项目]['musics'][第几个音轨]['set']['什么设置'] = '设置啥'
#
# 新增音轨: dataset[第几个项目]['musics'].append(datasetmodelpart)
#
'''
dataset=[
{
'mainset':{
'PackName':"Ryoun",
'MusicTitle':'Noname',
'IsRepeat':False,
'PlayerSelect':''
},
'musics':[
{
'set':{
'EntityName':'music_support',
'ScoreboardName':'music_support',
'Instrument':'harp',
'FileName':"Music"
},
'notes':[
[0.0,1.0],
]
},
],
},
]
'''
global dataset
dataset = [
{
'mainset': {
'PackName': "Ryoun",
'MusicTitle': 'Noname',
'IsRepeat': False,
'PlayerSelect': ''
},
'musics': [
{
'set': {
'EntityName': 'MusicSupport',
'ScoreboardName': 'MusicSupport',
'Instrument': 'note.harp',
'FileName': "Music"
},
'notes': [
[0.0, 1.0],
]
},
],
},
]
global is_new_file
global is_save
global ProjectName
global NowMusic
is_new_file = True
is_save = True
ProjectName = ''
NowMusic = 0
def DMM(): # 反回字典用于编辑
datasetmodelpart = {
'set': {
'EntityName': 'MusicSupport',
'ScoreboardName': 'MusicSupport',
'Instrument': 'note.harp',
'FileName': "Music"
},
'notes': []
}
return datasetmodelpart
print("完成")
# 菜单命令
print('加载菜单命令...')
def exitapp(cmd):
log("程序正常退出", False)
global is_save
if is_save == False:
if '/s' in cmd:
saveProject()
else:
print("您尚未保存,请使用 /s 开关保存并退出")
return False
try:
global dataset
del dataset
except:
pass
if '/c' in cmd:
print("清除log此句不载入日志")
try:
if os.path.exists("./log/"):
shutil.rmtree("./log/")
if os.path.exists("./logs/"):
shutil.rmtree("./logs/")
if os.path.exists("./cache/"):
shutil.rmtree("./cache/")
except:
print("无法清除日志及临时文件")
exit()
print('退出函数加载完成!')
print("载入文件读取函数")
def ReadFile(fn: str):
from nmcsup.nmcreader import ReadFile as fileRead
k = fileRead(fn)
if k == False:
log("找不到"+fn)
return False
else:
return k
def ReadMidi(midfile: str):
from nmcsup.nmcreader import ReadMidi as midiRead
k = midiRead(midfile)
if k == False:
log("找不到"+midfile)
return False
else:
return k
print('完成!')
print("载入命令函数")
def saveProject(cmd: list):
global is_new_file
if '/a' in cmd:
log("另存项目")
ProjectName = cmd[cmd.index('/a')+1]
else:
if is_new_file:
print("初次存储请使用 /a 开关规定存储文件名")
log("文件未保存")
return False
log("存储文件:"+ProjectName)
with open(ProjectName, 'w', encoding='utf-8') as f:
json.dump(dataset[0], f)
global is_save
is_save = True
print('保存项目函数加载完成!')
def loadMusic(cmd: list):
if '/mid' in cmd:
th = NewThread(ReadMidi, (cmd[cmd.index('/mid')+1],))
th.start()
def midiSPT(th):
for i in th.getResult():
datas = DMM()
datas['notes'] = i
dataset[0]['musics'].append(datas)
del th
global is_save
is_save = False
threading.Thread(target=midiSPT, args=(th,)).start()
del th
elif '/txt' in cmd:
th = NewThread(ReadFile, (cmd[cmd.index('/txt')+1],))
th.start()
def midiSPT(th):
for i in th.getResult():
datas = DMM()
datas['notes'] = i
dataset[0]['musics'].append(datas)
del th
global is_save
is_save = False
threading.Thread(target=midiSPT, args=(th,)).start()
elif '/input' in cmd:
datas = []
for i in cmd[cmd.index('/input')+1:]:
datas.append([str(i), 1.0])
from nmcsup.trans import note2list
datat = DMM()
datat['notes'] = note2list(datas)
dataset[0]['musics'].append(datat)
del datas, datat
global is_save
is_save = False
else:
log("无参数,无法读入。")
print("请查看帮助文件查看指令格式。")
return False
print('音轨载入函数加载完成!')
def funBuild(cmd: list):
if '/file' in cmd:
from msctspt.funcOpera import makeFuncFiles
makepath = cmd[cmd.index('/file')+1]
if makepath[-1] != '/':
makepath += '/'
makeFuncFiles(dataset[0], makepath)
elif '/directory' in cmd:
from msctspt.funcOpera import makeFunDir
makepath = cmd[cmd.index('/directory')+1]
if makepath[-1] != '/':
makepath += '/'
makeFunDir(dataset[0], makepath)
elif '/mcpack' in cmd:
import zipfile
from msctspt.funcOpera import makeFunDir
makepath = cmd[cmd.index('/mcpack')+1]
if makepath[-1] != '/':
makepath += '/'
if not os.path.exists('./temp/'):
os.makedirs('./temp/')
makeFunDir(dataset[0], './temp/')
shutil.move('./temp/'+dataset[0]['mainset']['PackName'] +
"Pack/behavior_packs/"+dataset[0]['mainset']['PackName']+"/functions", './')
shutil.move('./temp/'+dataset[0]['mainset']['PackName'] + "Pack/behavior_packs/" +
dataset[0]['mainset']['PackName']+"/manifest.json", './')
with zipfile.ZipFile(makepath+dataset[0]['mainset']['PackName']+'.mcpack', "w") as zipobj:
for i in os.listdir('./functions/'):
zipobj.write('./functions/'+i)
zipobj.write('./manifest.json')
shutil.move('./functions', './temp/')
shutil.move('./manifest.json', './temp/')
shutil.rmtree("./temp/")
else:
log("无参数,无法读入。")
print("请查看帮助文件查看指令格式。")
return False
print("函数建立函数加载完成")
def __main__():
if sys.platform == 'win32':
os.system("cls")
else:
os.system("clear")
if sys.platform in ('win32', 'linux'):
print("您当前的运行环境为标准桌面,您可以打开 Musicreater.py 运行窗口模式的 音·创")
print("您也可以输入 win 指令在不退出命令行模式的同时打开窗口模式\n")
print(__author__+" 音·创 —— 当前核心版本 "+__version__+'\n')
nowWorkPath = os.path.split(os.path.realpath(__file__))[0]
while True:
strcmd = input("MSCT "+nowWorkPath+">")
cmd = strcmd.lower().split(' ')
if cmd[0] == 'exit':
exitapp(cmd[1:])
elif cmd[0] == 'save':
saveProject(cmd[1:])
elif cmd[0] == 'load':
loadMusic(cmd[1:])
elif cmd[0] == 'win':
def run(cmd):
os.system(cmd)
if sys.platform == 'win32':
NewThread(run, ("python "+os.path.split(os.path.realpath(__file__))
[0]+"/Musicreater.py",)).start()
else:
NewThread(run, ("python3 "+os.path.split(os.path.realpath(__file__))
[0]+"/Musicreater.py",)).start()
elif cmd[0] == 'chdir':
nowWorkPath = os.path.realpath(cmd[1])
os.chdir(nowWorkPath)
elif cmd[0] == 'build':
funBuild(cmd[1:])
else:
os.system(strcmd)
if __name__ == '__main__':
__main__

View File

@@ -1,4 +0,0 @@
from musicreater.app import main
if __name__ == '__main__':
main().main_loop()

View File

@@ -1,133 +0,0 @@
"""
音·创(Musicreater)是由金羿(W-YI)开发的一款《我的世界》基岩版音乐生成辅助软件
"""
# W-YI 金羿
# QQ 2647547478
# 音·创 开发交流群 861684859
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com
# 版权所有 Team-Ryoun 金羿
# 若需转载或借鉴 请附作者
# 代码写的并非十分的漂亮还请大佬多多包涵本软件源代码依照Apache软件协议公开
import sys
import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW
from musicreater.Cmd_Msct import *
from musicreater.msctspt.bugReporter import version
from musicreater.resources.ChineseLang import LANGUAGE
__version__ = version.version[1]+version.version[0]
__author__ = 'W-YI (金羿)'
if sys.platform == 'win32':
os.chdir(__file__[:len(__file__)-__file__[len(__file__)::-1].index('\\')])
log("更新执行位置,当前文件位置"+__file__)
else:
try:
os.chdir(__file__[:len(__file__) -
__file__[len(__file__)::-1].index('/')])
except:
pass
log("其他平台:"+sys.platform+"更新执行位置,当前文件位置"+__file__)
class Musicreater(toga.App):
'''音·创 本体\n
W-YI 金羿\n
QQ 2647547478\n
音·创 开发交流群 861684859\n
Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com\n
版权所有 Team-Ryoun 金羿\n
若需转载或借鉴 请附作者\n
'''
def startup(self):
# Start to draw the window
main_box = toga.Box(style=Pack(direction=COLUMN))
self.noticeLabel = toga.Label('MSCT >>>',style=Pack(padding=(0, 5)))
self.inputBox = toga.TextInput(style=Pack(flex=1))
#dispImage = toga.ImageView("./resources/oddevenmatrix.png")
cmd_box = toga.Box(style=Pack(direction=ROW, padding=5))
cmd_box.add(self.noticeLabel)
cmd_box.add(self.inputBox)
# cmd_box.add(dispImage)
button = toga.Button(
LANGUAGE['main']['run'],
on_press=self.showMessage,
style=Pack(padding=5)
)
main_box.add(cmd_box)
main_box.add(button)
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()
self.main_window.info_dialog('',"{} {} —— {} {}".format(__author__,LANGUAGE['main']['name'],LANGUAGE['main']['version'],__version__))
self.nowWorkPath = os.path.split(os.path.realpath(__file__))[0]
def showMessage(self, widget):
strcmd = self.inputBox.value
cmd = strcmd.lower().split(' ')
if cmd[0] == 'exit':
if exitapp(cmd[1:]) == False:
self.main_window.info_dialog('',LANGUAGE['command']['FormatError'])
elif cmd[0] == 'save':
if saveProject(cmd[1:]) == False:
self.main_window.info_dialog('',LANGUAGE['command']['FormatError'])
elif cmd[0] == 'load':
if loadMusic(cmd[1:]) == False:
self.main_window.info_dialog('',LANGUAGE['command']['FormatError'])
elif cmd[0] == 'chdir':
self.main_window.info_dialog('',LANGUAGE['command']['NotAvailable'])
return
nowWorkPath = os.path.realpath(cmd[1])
os.chdir(nowWorkPath)
elif cmd[0] == 'build':
if funBuild(cmd[1:]) == False:
self.main_window.info_dialog('',LANGUAGE['command']['FormatError'])
else:
return
os.system(strcmd)
def main():
return Musicreater()

View File

@@ -1,141 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
__version__ = '0.0.1'
__all__ = ['run_server', 'subscribe', 'unsubscribe', 'send_command', 'tellraw']
__author__ = 'Fuckcraft <https://gitee.com/fuckcraft>'
import os
import json
import uuid
import logging
import asyncio
import time
import websockets
# 写这段代码的时候,只有我和上帝知道这段代码是干什么的。
# 现在只有上帝知道。
# 此函数用于向 Minecraft 订阅请求
async def subscribe(websocket, event_name):
'''
参数:
: websocket : websocket 对象 :
: event_name : 需要订阅的请求 :
返回:
None
'''
response = {
'body': {
'eventName': str(event_name) # 示例PlayerMessage
},
'header': {
'requestId': str(uuid.uuid4()),
'messagePurpose': 'subscribe',
'version': 1,
'messageType': 'commandRequest'
}
}
# 增加 json 的可读性
# response = json.dumps(response, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
response = json.dumps(response)
await websocket.send(response)
# 此函数用于向 Minecraft 消除订阅请求
async def unsubscribe(webscket):
'''
参数:
: websocket : websocket 对象 :
: event_name : 需要消除订阅的请求 :
返回:
None
'''
response = {
"body": {
"eventName": str(event_name) # PlayerMessage
},
"header": {
"requestId": str(uuid.uuid4()),
"messagePurpose": "unsubscribe",
"version": 1,
"messageType": "commandRequest"
}
}
# 增加 json 的可读性
# response = json.dumps(response, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
response = json.dumps(response)
await websocket.send(response)
# 此函数用于向 Minecraft 执行命令
async def send_command(websocket, command):
'''
参数:
: websocket : websocket 对象 :
: command : 执行的命令 :
返回:
None
'''
response = {
'body': {
'origin': {
'type': 'player'
},
'commandLine': str(command),
'version': 1
},
'header': {
'requestId': str(uuid.uuid4()),
'messagePurpose': 'commandRequest',
'version': 1,
'messageType': 'commandRequest'
}
}
# 增加 json 的可读性
# response = json.dumps(response, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
response = json.dumps(response)
await websocket.send(response)
# 此函数用于向 Minecraft 发送消息
async def tellraw(websocket, message):
'''
参数:
: websocket : websocket 对象 :
: message : 发送的消息 :
返回:
None
'''
command = {
'rawtext':[
{
'text':'[{}] {}'.format(time.asctime(), message)
}
]
}
# 增加 json 可读性
# command = json.dumps(command, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False)
command = json.dumps(command)
command = 'tellraw @a {}'.format(command)
await send_command(websocket, command)
def run_server(function):
# 修改 ip 地址和端口
start_server = websockets.serve(function, 'localhost', 8080)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

View File

@@ -1,2 +0,0 @@
00:13:19 更新执行位置当前文件位置F:\W-YI\Programming\音·创\程序\src\musicreater\Cmd_Msct.py
00:13:19 更新执行位置当前文件位置F:\W-YI\Programming\音·创\程序\src\musicreater\app.py

View File

@@ -1,173 +0,0 @@
音·创(Musicreater)是由金羿(W-YI)开发的一款《我的世界》基岩版音乐生成辅助软件
本软件源代码依照Apache软件协议公开。
Copyright © W-YI 2021
本软件是金羿前作函数音创和世界音创的集合版本,同时增加了大量功能更新。
To-Do
1.可以导出自定义的结构文件用于存储要导入地图中的结构
2.进度条
3.可以将音乐写入音符盒(红乐)
4.更换tk库为briefcase库支持安卓系统
5.支持自动给音符盒绑定更多的音色
6.可以由.schematic文件导入地图亦可反向处理
7.支持自定义指令方块区域的长宽高等
8.支持自定义创建websockeet服务器播放音乐感谢由 Fuckcraft <https://github.com/fuckcraft> “鸣凤鸽子”等 带来的我的世界websocket服务器功能
9.支持使用红石播放指令音乐
10.支持采用延时的播放器
11.支持使用bdx导出结构
12.支持采用tp的方法播放
13.支持识别曲谱图片解析音乐
14.支持使用瀑布流的方式播放音乐
15.帮助菜单
16.多语言
17.支持自动搜寻地图目录位置(网易&微软)
新更新日志
Beta 0.0.4.3
2021 11 3~2021 12 26
1.不断改进包以及代码可读性
2.修正部分源码错误
3.修正部分格式错误
4.加强对Linux系统的支持
5.新增命令行模式
6.代码中新增大量注释
Beta 0.0.4 ~ Beta 0.0.4.2
2021 11 20 ~ 2021 11 21
1.完全支持Linux系统
2.支持以.RyStruct导出结构
3.修复大量bug
4.支持拖拽打开参数1为.msct文件
Beta 0.0.3.1~0.0.3.5
2021 11 1~2021 11 2
1.更新部分提示信息使之更加科学
2.强制性限制不得使用非Win32平台打开此程序
3.支持在Windwos7上使用此程序发现错误并解决DLL缺失MSVCP140.dll
4.开始对结构导出进行部分支持
5.发现红乐写入的错误,正在排查修复
Beta 0.0.3
2021 10 29 ~ 2021 10 31
1.修改部分窗口排版
2.修复指令载入地图的结构的错误
3.修复指令生成出现的指令错误(感谢 昀梦<QQ1515399885> 找出bug并指正
4.支持生成红石音乐(以音符盒存储的音乐),并写入地图
5.修复了生成指令音乐导致的错误
6.修复bdx文件y轴过长导致无法生成完毕的错误现在bdx的y轴为200格
Beta 0.0.2
2021 10 25
1.修复了邮件发送错误报告无法生成压缩包的问题
2.修复了导入音轨时无法获得进程返回值的问题
3.修复了.bdx文件生成时无法选择文件的问题
4.修复了生成指令音乐(计分板)没有起始方块的问题
5.新增了创建Websocket的功能可以在localhost:8080创建websocket服务器播放音乐感谢由 Fuckcraft <https://gitee.com/fuckcraft> “鸣凤鸽子”等 带来的我的世界websocket服务器功能(fcwslib)
6.解决了打包成可执行文件时无法正常退出的问题
Beta 0.0.1
2021 10月
1.支持生成.bdx文件感谢由 Charlie_Ping “查理平” 带来的bdx转换功能
2.逐步增强对安卓系统的支持
3.逐步放弃对Windows的强行要求
4.逐步提升性能,增加多线程
Alpha部分更新日志
Alpha 0.0.0
2021 8 20
1.集合了 函数音创0.1.4.1 与 世界音创Beta0.0.1 的功能于本应用
2.新增了可以生成 .mcpack 包的方法
Alpha 0.0.1
2021 8 25
1.新增两个彩蛋(就是函数音创命令行模式的彩蛋
Alpha 0.0.1.1
2021 8 25
1.修复大量已知问题
2.修复了部分彩蛋bug但是程序仍然不会正常退出
3.菜单界面优化
Alpha 0.0.1.2
2021.8.29
1.修复大量已知问题
2.现在可以操作指令文件了
3.窗口界面优化
Alpha 0.0.2
2021 9 5
1.修复部分已知问题
2.指令链导入之时仅生成链式方块且允许折转
3.[Dev]正在逐步支持结构导出
Alpha 0.0.3
2021 9 7
1.修复指令链转入世界的摆放错误
2.指令存储的音乐(包括函数)支持不同玩家不同的播放
3.支持播放进度条
4.删除彩蛋任务栏图标
4.[Dev]已确定导出结构格式
Alpha 0.0.3.1
2021 9 11
1.取消输入玩家选择器时不会出现bug了
2.删除日志文件修改为删除临时文件
3.可以删除用于确认档案存在的文件了
Alpha 0.0.4
2021 10 4-5
1.可以将大函数导入世界(以一条链执行多个函数的方式)
2.关闭了试听音乐的功能但是保留其函数于funOpera.py中
3.修改部分代码减少更多bug
4.发现指令链转入世界的摆放错误,但是没改正
1.0.3
2021 10 5-6
1.解决一些已知问题
2.解决了文件读取造成的字符编码问题
3.使用PyPinyin库将汉字转化为拼音首字母
Alpha 0.0.4.1
2021 10 9
1.将清除日志功能设置为结束后统一清除,避免了清除过程中文件占用导致的问题
Alpha 0.0.5
2021 10 10
1.支持使用邮件方式发送错误报告(日志)
Alpha 0.0.5.1
1.修复了邮件发送错误报告无法发送的问题
2.修复了打包成.exe文件之后无法正常退出的问题

View File

@@ -1,215 +0,0 @@
import os
import brotli
'''感谢由 Charlie_Ping “查理平” 带来的bdx转换代码'''
class BdxConverter:
__header = "BD@"
__bin_header = b"BDX"
__generator_author = b"&Charlie_Ping"
keys = {
# x--, x++, addSmallX(-128~127), addX(-32768~32767), addBigX(-2147483648~2147483647)
"x": [b"\x0f", b"\x0e", b"\x1c", b"\x14", b"\x15"],
"y": [b"\x11", b"\x10", b"\x1d", b"\x16", b"\x17"],
"z": [b"\x13", b"\x12", b"\x1e", b"\x18", b"\x19"],
"end": b"\x58",
"isSigned": b"\x5a",
"placeCommandBlockWithData": b"\x1b",
"placeBlock": b"\x07"
}
def __init__(self, file_path: str, author: str, blocks):
self.author = author
self.blocks = blocks
self.file_path = file_path
self.direction = [0, 0, 0]
self.block_type = self.get_block_type
self.__file = self.create_and_upload_file
@property
def get_block_type(self):
"""
blocks
[
{
"direction": [x: int, y: int, z: int],
block_name: str,
particular_value: int,
}
]
:return: list 给出的所有方块种类名称
"""
block_type = set()
for block in self.blocks:
block_type.add(block["block_name"])
block_type = list(block_type)
return block_type
@property
def create_and_upload_file(self):
"""
瞎用property 害怕
创建一个bdx文件
要close
:return: 一个文件对象
"""
_dir = os.path.dirname(self.file_path)
if not os.path.isdir(_dir):
os.makedirs(_dir)
_bytes = self.__bin_header
_bytes += b"\x00"
_bytes += self.author.encode("utf-8") + self.__generator_author
for i in self.block_type:
_bytes += b"\x00\x01"
_bytes += bytes(i, encoding="utf-8")
_bytes += b"\x00"
_bytes += self.upload_blocks()
_bytes += b"X"
with open(self.file_path, "w+") as f:
f.write("BD@")
f.close()
with open(self.file_path, "ab+") as f:
f.write(brotli.compress(_bytes))
f.close()
return
def upload_blocks(self):
"""
计算差值
写入移动过程
写入方块
更新差值
:return:
"""
_types = b""
for block in self.blocks:
# print(f"当前方块:{block['block_name']}, 位置: {block['direction']}]")
diff = self.move_pointer(self.direction, block["direction"])
_types += diff
if block["block_name"] in ["command_block",
"chain_command_block",
"repeating_command_block"]:
_types += self.obtain_command_block(block)
else:
_types += self.obtain_universal_block(block)
self.direction = block["direction"]
return _types
def move_pointer(self, direction: list, new_direction):
"""
给出 两个[x, y, z]坐标返回pointer的移动过程
:param direction: 坐标 1
:param new_direction: 坐标 2
:return: bytes
"""
_bytes = b""
for i, sign in enumerate(["x", "y", "z"]):
# print(f"<{sign}> 新-旧={new_direction[i]-direction[i]}")
distance = new_direction[i] - direction[i]
if distance == 0:
# print("距离是0跳过了")
continue
_bytes += self.obtain_pointer_type(distance, sign)
# print(f"向 {sign} 运动了 {distance} 格子")
return _bytes
@classmethod
def obtain_pointer_type(cls, num: int, coordinate: str):
"""
用于确定辅助玩家以某一数据类型走指定长度
-1 -> 0
1 -> 1
[128, 127] -> 2
[-32768, 32767] -> 3
[-2147483648, 2147483647] -> 4
:param num:
:param coordinate: 坐标轴种类x y 或 z
:return:
"""
if num == 0:
return
pointer = 0
condition = (num != -1, # byte=0, pointer=1
num < -1 or num > 1, # byte=1, pointer=2
num < -128 or num > 127, # byte=2, pointer=3
num < -32768 or num > 32767, # byte=4, pointer=4
)
for i in condition:
if i:
pointer += 1
pointer_type = cls.keys[coordinate][pointer]
byte_len = 2 ** (pointer - 2)
if byte_len >= 1:
num_byte = num.to_bytes(byte_len, byteorder="big", signed=True)
return pointer_type + num_byte
return pointer_type
def obtain_universal_block(self, block):
"""
给定一个方块, 返回此方块在这个bdx中的id和方块data
:param block: {block_name: str,particular_value: int}
:return: bytes
"""
block_id = b"\x07" + self.block_type.index(block["block_name"]).to_bytes(2, byteorder="big", signed=False)
particular_value = block["particular_value"].to_bytes(2, byteorder="big", signed=False)
block_header = block_id + particular_value
return block_header
def obtain_command_block(self, block):
"""
给定一个命令方块,返回命令方块各种数据
:param block: {
"direction": [x: int, y: int, z: int]
"block_name": str,
"particular_value": int,
"impluse": int, # unsigned_int32
"command": str,
"customName": str,
"lastOutput": str, # 没特殊要求写个\x00就得了
"tickdelay": int, # int32
"executeOnFirstTick": int, # 1 bytes
"trackOutput": int, # 1 bytes
"conditional": int, # 1 bytes
"needRedstone": int # 1 bytes
}
:return: bytes of command_block
"""
block_id = b"\x1b" + self.block_type.index(block["block_name"]).to_bytes(2, byteorder="big", signed=False)
particular_value = block["particular_value"].to_bytes(2, byteorder="big", signed=False)
block_header = block_id + particular_value
for i in [
block["impluse"].to_bytes(4, byteorder="big", signed=False),
bytes(block["command"], encoding="utf-8") + b"\x00",
bytes(block["customName"], encoding="utf-8") + b"\x00",
bytes(block["lastOutput"], encoding="utf-8") + b"\x00",
block["tickdelay"].to_bytes(4, byteorder="big", signed=True),
block["executeOnFirstTick"].to_bytes(1, byteorder="big"),
block["trackOutput"].to_bytes(1, byteorder="big"),
block["conditional"].to_bytes(1, byteorder="big"),
block["needRedstone"].to_bytes(1, byteorder="big")
]:
block_header += i
return block_header
if __name__ == '__main__':
block = [{"direction": [-1, -1, -1], "block_name": "concrete", "particular_value": 5},
{"direction": [1, 5, 1], "block_name": "stained_glass", "particular_value": 7},
{"direction": [2, 4, 1], "block_name": "command_block", "particular_value": 3,
"impluse": 0,
"command": "say A generator test",
"customName": "test",
"lastOutput": "",
"tickdelay": 24,
"executeOnFirstTick": 0,
"trackOutput": 0,
"conditional": 0,
"needRedstone": 1
},
{"direction": [3, 4, 1], "block_name": "concrete", "particular_value": 6},
{"direction": [-123412133, 4, 1], "block_name": "concrete", "particular_value": 7}]
bdx = BdxConverter("./test02.bdx", "Charlie_Ping",block)

View File

@@ -1,134 +0,0 @@
# -*- coding: UTF-8 -*-
'''提供错误报告的基本操作及方法 顺便提供版本更新、安装库等功能'''
def makeZip(sourceDir, outFilename,compression = 8,exceptFile = None):
'''使用compression指定的算法打包目录为zip文件\n
默认算法为DEFLATED(8),可用算法如下:\n
STORED = 0\n
DEFLATED = 8\n
BZIP2 = 12\n
LZMA = 14\n
'''
import os, zipfile
zipf = zipfile.ZipFile(outFilename, 'w',compression)
pre_len = len(os.path.dirname(sourceDir))
for parent, dirnames, filenames in os.walk(sourceDir):
for filename in filenames:
if filename == exceptFile:
continue;
print(filename)
pathfile = os.path.join(parent, filename)
arcname = pathfile[pre_len:].strip(os.path.sep) #相对路径
zipf.write(pathfile, arcname)
zipf.close()
del zipf,pre_len
#以上函数节选并修改自 正在攀登的小蜗牛 的博客https://blog.csdn.net/qq_21127151/article/details/107503942
class report():
'''发送报告以及相应的任务处理'''
def __init__(self,senderName:str = 'Unknown',senderContact:str = 'None',describetion:str = ''):
''':param senderName 发送者名称
:param senderContact 发送者联系方式
:param describetion 问题描述'''
self.senderName = senderName;
self.senderContact = senderContact;
self.describetion = describetion;
if not self.senderName :
self.senderName = 'Unknown';
if not self.senderContact :
self.senderContact = 'None';
def emailReport(self):
'''使用E-mail方法发送当前的日志和临时文件等'''
import smtplib
from email.mime.text import MIMEText;
from email.mime.multipart import MIMEMultipart;
from email.header import Header;
from musicreater.nmcsup.log import log
log("发送错误报告")
import os;
log("添加标题与正文")
msg = MIMEMultipart();
#发送者与接收者显示名称
msg["From"] = Header(self.senderName,'utf-8');
msg["To"] = Header("W-YI (QQ2647547478)",'utf-8');
#标题
msg["Subject"] = '音·创 - 来自 '+self.senderName+' 的错误报告';
#正文
msg.attach(MIMEText("来自"+self.senderName+"( "+self.senderContact+" )的错误描述:\n"+self.describetion,'plain','utf-8'));
log("添加完毕,正在生成压缩包...")
makeZip("./","Temps&Logs.zip",exceptFile="Temps&Logs.zip");
attafile=MIMEText(open("Temps&Logs.zip",'rb').read(),"base64",'gb2312');
attafile["Content-Type"] = 'application/octet-stream';
attafile["Content-Disposition"] = 'attachment;filename="BugReport_from_'+self.senderName+'.zip"';
msg.attach(attafile);
log("完毕,准备发送")
try:
smtp = smtplib.SMTP()
smtp.connect("smtp.163.com");
#SIQQKQQYCZRVIDFJ是授权密码
smtp.login("RyounDevTeam@163.com","SIQQKQQYCZRVIDFJ");
smtp.sendmail("RyounDevTeam@163.com",["RyounDevTeam@163.com",],msg.as_string())
log("错误汇报邮件已发送")
except smtplib.SMTPException as e:
log("错误汇报邮件发送失败:\n"+str(e));
log("清空内存和临时文件")
del msg,attafile
os.remove("./Temps&Logs.zip")
class version:
libraries = ('mido','amulet','amulet-core','amulet-nbt','piano_transcription_inference','pypinyin','briefcase','toga','pyinstaller','py7zr','websockets','torch')
'''当前开发所需库'''
version = ('0.0.0','Gamma',)
'''当前版本'''
def __init__(self) -> None:
self.libraries = version.libraries
'''当前开发所需库'''
self.version = version.version
'''当前版本'''
def installLibraries(self):
'''安装全部开发用库'''
from sys import platform
import os
if platform == 'win32':
import shutil
try:
shutil.rmtree(os.getenv('APPDATA')+'\\Musicreater\\')
except:
pass;
for i in self.libraries:
print("安装库:"+i)
os.system("python -m pip install "+i+" -i https://pypi.tuna.tsinghua.edu.cn/simple")
elif platform == 'linux':
os.system("sudo apt-get install python3-pip")
os.system("sudo apt-get install python3-tkinter")
for i in self.libraries:
print("安装库:"+i)
os.system("sudo python3 -m pip install "+i+" -i https://pypi.tuna.tsinghua.edu.cn/simple")

View File

@@ -1,215 +0,0 @@
# -*- coding: utf-8 -*-
"""音·创 的函数操作和一些其他功能"""
def delPart(Data,starter,ender,includeStart :bool= True,includend :bool= True):
'''删除序列从starter物件到ender物件之间的部分\n
includeStart与inclodend分别控制此函数是否包括starter和ender物件所在部分默认为真\n
starter与ender若为None则默认从首或尾开始'''
try:
if starter == None:
includeStart = True;
starter = Data[0];
if ender == None:
includend = True;
ender = Data[len(Data)-1];
if includend:
if includeStart:
return Data[Data.index(starter):len(Data)-Data[len(Data)::-1].index(ender)];
else:
return Data[Data.index(starter)+1:len(Data)-Data[len(Data)::-1].index(ender)];
else:
if includeStart:
return Data[Data.index(starter):len(Data)-Data[len(Data)::-1].index(ender)-1];
else:
return Data[Data.index(starter)+1:len(Data)-Data[len(Data)::-1].index(ender)-1];
except:
return 0
def keepart(Data,starter,ender,includeStart :bool= True,includend :bool= True):
'''保留序列从starter物件到ender物件之间的部分\n
includeStart与inclodend分别控制此函数是否包括starter和ender物件所在部分默认为真\n
starter与ender若为None则默认从首或尾开始'''
try:
if starter == None:
includeStart = True;
starter = Data[0];
if ender == None:
includend = True;
ender = Data[len(Data)-1];
if includend:
if includeStart:
return Data[Data.index(starter):Data.index(ender)+1];
else:
return Data[Data.index(starter)+1:Data.index(ender)+1];
else:
if includeStart:
return Data[Data.index(starter):Data.index(ender)];
else:
return Data[Data.index(starter)+1:Data.index(ender)];
except:
return 0
def lenFunction(fun) -> int:
'''取得函数指令部分长度,即忽略#开头的注释'''
try:
l = 0;
for i in fun:
if i.replace(" ",'')[0] == '#':
l += 1;
return len(fun)-l;
except:
return -1;
def funSplit(bigFile,maxCmdLen : int = 10000 ):
'''分割bigFile大的函数文件bigFile需要读入文件流\n
返回的部分,每行指令皆带有行尾换行符\\n\n
返回-1为大小低于maxCmdLen最长函数指令长度'''
bigFile = bigFile.readlines()
if lenFunction(bigFile) < maxCmdLen:
return -1;
part = [];
parts = [];
l = 0;
for i in bigFile:
if i.replace(" ",'')[0] == '#':
part.append(i+'\n');
else:
part.append(i+'\n');
l += 1;
if l >= 10000:
parts.append(part)
part = [];
l = 0;
return parts;
def makeFuncFiles(musicset, path='./'):
from musicreater.nmcsup.log import log
'''在指定目录下生成函数文件'''
from musicreater.nmcsup.trans import Note2Cmd
commands = []
starts = []
log("=========================正在在此处生成文件:"+path)
maxlen = -1
for i in range(len(musicset['musics'])):
log('写入第'+str(i)+'个数据')
commands.append("scoreboard players add @e[name=\""+musicset['musics'][i]['set']['EntityName']+"\"] "+musicset['musics'][i]['set']['ScoreboardName']+" 1\n")
commands.append("execute @e[name=\""+musicset['musics'][i]['set']['EntityName'] +"\",scores={"+musicset['musics'][i]['set']['ScoreboardName']+"=1..10}] ~~~ title @a"+musicset['mainset']['PlayerSelect']+" title "+musicset['mainset']['MusicTitle']+"\n")
commands.append("execute @e[name=\""+musicset['musics'][i]['set']['EntityName'] +"\",scores={"+musicset['musics'][i]['set']['ScoreboardName']+"=1..10}] ~~~ title @a"+musicset['mainset']['PlayerSelect']+" subtitle 本函数乐曲由§b§l凌云§r§3函数音乐创建§r生成\n")
if len(musicset['musics'][i]['notes']) > maxlen:
maxlen = len(musicset['musics'][i]['notes'])
starts.append("scoreboard objectives add " +musicset['musics'][i]['set']['ScoreboardName']+" dummy\n")
starts.append("summon armor_stand " +musicset['musics'][i]['set']['EntityName']+'\n')
with open(path+musicset['mainset']['MusicTitle']+'_Part'+str(i)+'.mcfunction', 'w', encoding='UTF-8') as f:
f.writelines(Note2Cmd(musicset['musics'][i]['notes'],musicset['musics'][i]['set']['ScoreboardName'],musicset['musics'][i]['set']['Instrument'],musicset['mainset']['PlayerSelect'],True))
if musicset['mainset']['IsRepeat']:
log("增加重复语句")
for i in range(len(musicset['musics'])):
commands.append("execute @e[name=\""+musicset['musics'][i]['set']['EntityName']+"\",scores={"+musicset['musics'][i]['set']['ScoreboardName']+"="+str((maxlen+2)*10)+"}] ~~~ scoreboard players set @e[name=\""+musicset['musics'][i]['set']['EntityName']+"\"] "+musicset['musics'][i]['set']['ScoreboardName']+" -1\n")
log("增加版权语句")
commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI金羿\n")
starts.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI金羿\n")
log("写入支持文件")
with open(path+musicset['mainset']['MusicTitle']+'_Support.mcfunction', 'w', encoding='UTF-8') as f:
f.writelines(commands)
log("写入开始文件")
with open(path+'Start_'+musicset['mainset']['MusicTitle']+'.mcfunction', 'w', encoding='UTF-8') as f:
f.writelines(starts)
del commands, starts, maxlen
log("完成============================")
def makeFunDir(musicset, path='./'):
from musicreater.nmcsup.log import log
'''在指定目录下生成函数包文件夹'''
import os
import uuid
log("=============================生成函数包文件夹")
# note,packname="Ryoun",FileName="Music",EntityName_='music_support',ScoreboardName_='music_support',MusicTitle_='Noname',PlayerSelect_='',Repeat_=False,Instrument_='harp'
try:
os.makedirs(path+musicset['mainset']['PackName'] +"Pack/behavior_packs/"+musicset['mainset']['PackName']+"/functions")
log("已创建目录"+path+musicset['mainset']['PackName'] +"Pack/behavior_packs/"+musicset['mainset']['PackName']+"/functions")
except:
log("目录已有无需创建")
pass
# 判断文件皆存在
if not(os.path.exists(path+musicset['mainset']['PackName']+"Pack/world_behavior_packs.json") and os.path.exists(path+musicset['mainset']['PackName']+"Pack/behavior_packs/"+musicset['mainset']['PackName']+"/manifest.json")):
log("创建manifest.json以及world_behavior_packs.json")
behaviorUuid = uuid.uuid4()
with open(path+musicset['mainset']['PackName']+"Pack/world_behavior_packs.json", "w") as f:
f.write("[\n {\"pack_id\": \"" + str(behaviorUuid) +"\",\n \"version\": [ 0, 0, 1 ]}\n]")
with open(path+musicset['mainset']['PackName']+"Pack/behavior_packs/"+musicset['mainset']['PackName']+"/manifest.json", "w") as f:
f.write("{\n \"format_version\": 1,\n \"header\": {\n \"description\": \""+musicset['mainset']['PackName']+" Pack : behavior pack\",\n \"version\": [ 0, 0, 1 ],\n \"name\": \""+musicset['mainset']['PackName']+"Pack\",\n \"uuid\": \"" + str(behaviorUuid) + "\"\n },\n \"modules\": [\n {\n \"description\": \""+musicset['mainset']['PackName']+" Pack : behavior pack\",\n \"type\": \"data\",\n \"version\": [ 0, 0, 1 ],\n \"uuid\": \"" + str(uuid.uuid4()) + "\"\n }\n ]\n}")
makeFuncFiles(musicset, path+musicset['mainset']['PackName'] +"Pack/behavior_packs/"+musicset['mainset']['PackName']+"/functions/")
log("完成============================")
'''
这里是往事,用于记载一些用不到的功能
#存在于 Musicreater.py 播放(试听)音乐
def PlayNote(Notes, t=480): # Notes是音符列表t是一拍占有的毫秒数
tkinter.messagebox.showinfo(title='提示!', message="播放发音不一定标准\n说不定还会坏音响/(ㄒoㄒ)/~~qwq\n请注意。")
import winsound
import time
from nmcsup.trans import mcnote2freq
Notes = mcnote2freq(Notes)
for frequency, duration in Notes:
log("播放:"+str([int(frequency), int(duration*t)]))
if int(frequency) != 0:
winsound.Beep(int(frequency), int(duration*t))
elif int(frequency) == 0:
time.sleep(duration*t/1000)
#同上,执行播放命令
def PlayOne():
log("试听")
tkinter.messagebox.showwarning(title="警告⚠", message="试听音质可能引起您的不适,更可能引起您的扬声器的不适,请酌情播放。")
global NowMusic
PlayNote(dataset[0]['musics'][NowMusic]['notes'])
#同上,是早期 MinecraftMusicFunctionMaker.py (函数音创)的代码转移至音·创时的注解
n2c(dataset[0]['musics'][i]['notes'],EntityName=dataset[0]['musics'][i]['set']['EntityName'],ScoreboardName=dataset[0]['musics'][i]['set']['ScoreboardName'],PlayerSelect=dataset[0]['mainset']['PlayerSelect'],Instrument=dataset[0]['musics'][i]['set']["Instrument"])
'''

View File

@@ -1,27 +0,0 @@
import threading
class NewThread(threading.Thread):
'''新建一个进程来运行函数,函数运行完毕后可以使用.getResult方法获取其返回值'''
def __init__(self, func, args=()):
super(NewThread, self).__init__()
self.func = func
self.args = args
def run(self):
self.result = self.func(*self.args)
def getResult(self):
threading.Thread.join(self) # 等待线程执行完毕
try:
return self.result
except Exception:
return None
#
# ————————————————
# 版权声明上面的类NewThread修改自CSDN博主「星火燎愿」的原创文章中的内容遵循CC 4.0 BY-SA版权协议转载请附上原文出处链接及本声明。
# 原文链接https://blog.csdn.net/xpt211314/article/details/109543014
# ————————————————
#

View File

@@ -1,308 +0,0 @@
"""音·创 的转换工具库"""
def hans2pinyin(hans,style=3):
"""将汉字字符串转化为拼音字符串"""
from pypinyin import lazy_pinyin
result = lazy_pinyin(hans=hans,style=style)
final = ''
for i in result:
final += i;
return final
def formCmdBlock(direction:list,command:str,particularValue:int,impluse:int,condition:bool=False,needRedstone:bool=True,tickDelay:int=0,customName:str='',lastOutput:str='',executeOnFirstTick:bool=False,trackOutput:bool=True):
"""
使用指定项目返回指定的指令方块格式字典
:param block: {
"direction": [x: int, y: int, z: int] #方块位置
"block_name": str, #方块名称无需指定默认为command_block
"particular_value": int, #方块特殊值
"impluse": int, #方块类型0脉冲 1循环 2连锁 unsigned_int32
"command": str, #指令
"customName": str, #悬浮字
"lastOutput": str, #上次输出
"tickdelay": int, #方块延时 int32
"executeOnFirstTick": int, #执行第一个选项 1 bytes
"trackOutput": int, #是否输出 1 bytes
"conditional": int, #是否有条件 1 bytes
"needRedstone": int #是否需要红石 1 bytes
}
:return: 指令方块字典结构
"""
return {"direction": direction,
"block_name": "command_block",
"particular_value": particularValue,
"impluse": impluse,
"command": command,
"customName": customName,
"lastOutput": lastOutput,
"tickdelay": tickDelay,
"executeOnFirstTick": executeOnFirstTick,
"trackOutput": trackOutput,
"conditional": condition,
"needRedstone": needRedstone
}
def note2bdx(filePath:str,dire:list,Notes : list,ScoreboardName:str,Instrument:str, PlayerSelect:str='',isProsess:bool=False,height:int = 200) :
'''使用方法同Note2Cmd
:param 参数说明:
filePath: 生成.bdx文件的位置
dire: 指令方块在地图中生成的起始位置(相对位置)
Notes: 以 list[ list[ float我的世界playsound指令音调 , float延续时常单位s ] ] 格式存储的音符列表 例如Musicreater.py的(dataset[0]['musics'][NowMusic]['notes'])
ScoreboardName: 用于执行的计分板名称
Instrument: 播放的乐器
PlayerSelect: 执行的玩家选择器
isProsess: 是否显示进度条(会很卡)
height: 生成结构的最高高度
:return 返回一个BdxConverter类实际上没研究过同时在指定位置生成.bdx文件'''
from musicreater.msctspt.transfer import formCmdBlock
from musicreater.nmcsup.trans import Note2Cmd
from musicreater.msctspt.bdxOpera_CP import BdxConverter
cmd = Note2Cmd(Notes,ScoreboardName,Instrument, PlayerSelect,isProsess)
cdl = []
for i in cmd:
try:
if (i[:i.index('#')].replace(' ','') != '\n') and(i[:i.index('#')].replace(' ','') != ''):
cdl.append(i[:i.index('#')])
except:
cdl.append(i)
i = 0
down = False
blocks = [formCmdBlock(dire,cdl.pop(0),1,1)]
dire[1]+=1;
for j in cdl:
if dire[1]+i > height:
dire[0]+=1
i=0
down = not down
if dire[1]+i == height :
blocks.append(formCmdBlock([dire[0],dire[1]+i,dire[2]],j,5,2,False,False))
else:
if down:
blocks.append(formCmdBlock([dire[0],dire[1]+i,dire[2]],j,0,2,False,False))
else:
blocks.append(formCmdBlock([dire[0],dire[1]+i,dire[2]],j,1,2,False,False))
i+=1
del i, cdl, down, cmd
return BdxConverter(filePath,'Build by RyounMusicreater',blocks)
def note2webs(Notes : list,Instrument:str, speed:float = 5.0, PlayerSelect:str='',isProsess:bool=False) :
'''传入音符在oaclhost:8080上建立websocket服务器以供我的世界connect/wssever指令连接
:param 参数说明:
Notes: 以 list[ list[ float我的世界playsound指令音调 , float延续时常单位s ] ] 格式存储的音符列表 例如Musicreater.py的(dataset[0]['musics'][NowMusic]['notes'])
Instrument: 播放的乐器
speed: 用于控制播放速度,数值越大,播放速度越快,相当于把一秒变为几拍
PlayerSelect: 执行的玩家选择器
isProsess: 是否显示进度条
:return None'''
import time
import fcwslib
import asyncio
from musicreater.nmcsup.log import log
from musicreater.nmcsup.vers import VER
async def run_server(websocket, path):
log('服务器连接创建')
await fcwslib.tellraw(websocket, '已连接服务器——音·创'+VER[1]+VER[0]+' 作者:金羿(W-YI)')
if isProsess:
length = len(Notes)
j = 1;
for i in range(len(Notes)):
await fcwslib.send_command(websocket,'execute @a'+PlayerSelect+' ~ ~ ~ playsound '+Instrument+' @s ~ ~ ~ 1000 '+str(Notes[i][0])+' 1000')
if isProsess:
fcwslib.send_command(websocket,'execute @a'+PlayerSelect+' ~ ~ ~ title @s actionbar §e▶ 播放中: §a'+str(j)+'/'+str(length)+' || '+str(int(j/length*1000)/10))
j+=1;
time.sleep(Notes[i][1]/speed)
fcwslib.run_server(run_server)
import amulet
from amulet.api.block import Block
from amulet.utils.world_utils import block_coords_to_chunk_coords as bc2cc
from amulet_nbt import TAG_String as ts
from nmcsup.log import log
def note2RSworld(world:str,startpos:list,notes:list,instrument:str,speed:float = 2.5,posadder:list = [1,0,0],baseblock:str = 'stone') -> bool:
'''传入音符,生成以音符盒存储的红石音乐
:param 参数说明:
world: 地图文件的路径
startpos: list[int,int,int] 开始生成的坐标
notes: list[list[float,float]] 以 list[ list[ float我的世界playsound指令音调 , float延续时常单位s ] ] 格式存储的音符列表 例如Musicreater.py的dataset[0]['musics'][NowMusic]['notes']
instrument: 播放的乐器
speed: 一拍占多少个中继器延迟(红石刻/rt)
posadder: list[int,int,int] 坐标增加规律,即红石的延长时按照此增加规律增加坐标
baseblock: 在中继器下垫着啥方块呢~
:return 是否生成成功
'''
from musicreater.msctspt.values import height2note,instuments
def formNoteBlock(note:int,instrument:str='note.harp',powered:bool = False):
'''生成音符盒方块
:param note: 0~24
:return Block()'''
if powered:
powered = 'true';
else:
powered = 'false';
return Block('universal_minecraft','noteblock',{"instrument":ts(instrument.replace("note.",'')),'note':ts(str(note)),'powered':ts(powered)})
def formRepeater(delay:int,facing:str,locked:bool=False,powered:bool=False):
'''生成中继器方块
:param delay: 1~4
:return Block()'''
if powered:powered = 'true';
else:powered = 'false';
if locked:locked = 'true';
else:locked = 'false';
return Block('universal_minecraft','repeater',{"delay":ts(str(delay)),'facing':ts(facing),'locked':ts(locked),'powered':ts(powered)})
level = amulet.load_level(world)
def setblock(block:Block,pos:list):
'''pos : list[int,int,int]'''
cx, cz = bc2cc(pos[0], pos[2])
chunk = level.get_chunk(cx, cz, "minecraft:overworld")
offset_x, offset_z = pos[0] - 16 * cx, pos[2] - 16 * cz
chunk.blocks[offset_x, pos[1], offset_z] = level.block_palette.get_add_block(block)
chunk.changed = True
# 1拍 x 2.5 rt
def placeNoteBlock():
for i in notes:
try :
setblock(formNoteBlock(height2note[i[0]],instrument),[startpos[0],startpos[1]+1,startpos[2]])
setblock(Block("universal_minecraft",instuments[i[0]][1]),startpos)
except :
log("无法放置音符:"+str(i)+''+str(startpos))
setblock(Block("universal_minecraft",baseblock),startpos)
setblock(Block("universal_minecraft",baseblock),[startpos[0],startpos[1]+1,startpos[2]])
delay = int(i[1]*speed+0.5)
if delay <= 4:
startpos[0]+=1
setblock(formRepeater(delay,'west'),[startpos[0],startpos[1]+1,startpos[2]])
setblock(Block("universal_minecraft",baseblock),startpos)
else:
for i in range(int(delay/4)):
startpos[0]+=1
setblock(formRepeater(4,'west'),[startpos[0],startpos[1]+1,startpos[2]])
setblock(Block("universal_minecraft",baseblock),startpos)
if delay % 4 != 0:
startpos[0]+=1
setblock(formRepeater(delay%4,'west'),[startpos[0],startpos[1]+1,startpos[2]])
setblock(Block("universal_minecraft",baseblock),startpos)
startpos[0]+=posadder[0]
startpos[1]+=posadder[1]
startpos[2]+=posadder[2]
try:
placeNoteBlock()
except:
log("无法放置方块了,可能是因为区块未加载叭")
level.save()
level.close()
class ryStruct:
def __init__(self,world:str) -> None:
self.RyStruct = dict()
self._world = world
self._level = amulet.load_level(world)
def reloadLevel(self):
try:
self._level = amulet.load_level(self.world)
except:
log("无法重载地图")
def closeLevel(self):
try:
self._level.close()
except:
log("无法关闭地图")
def world2Rys(self,startp:list,endp:list,includeAir:bool=False):
'''将世界转换为RyStruct字典注意此函数运行成功后将关闭地图若要打开需要运行 reloadLevel
:param startp: [x,y,z] 转化的起始坐标
:param endp : [x,y,z] 转换的终止坐标,注意,终止坐标需要大于起始坐标,且最终结果包含终止坐标
:param includeAir : bool = False 是否包含空气,即空气是否在生成之时覆盖地图内容
:return dict RyStruct '''
level = self._level
for x in range(startp[0],endp[0]+1):
for y in range(startp[1],endp[1]+1):
for z in range(startp[2],endp[2]+1):
RyStructBlock = dict()
cx, cz = bc2cc(x, z)
chunk = level.get_chunk(cx, cz, "minecraft:overworld")
universal_block = chunk.block_palette[chunk.blocks[x - 16 * cx, y, z - 16 * cz]]
if universal_block == Block("universal_minecraft","air") and includeAir:
continue
universal_block_entity = chunk.block_entities.get((x, y, z), None)
RyStructBlock["block"] = str(universal_block)
RyStructBlock["blockEntity"] = str(universal_block_entity)
log("载入方块数据"+str(RyStructBlock))
self.RyStruct[(x,y,z)] = RyStructBlock
level.close()
return self.RyStruct
'''
RyStruct = {
(0,0,0) = {
"block": str 完整的方块结构
"blockEntity": str | 'None'
}
}
'''

View File

@@ -1,59 +0,0 @@
instuments = {
'note.banjo' : ['班卓琴','hay_block'],
'note.bass' : ['贝斯','planks'],
'note.bassattack' : ['低音鼓/贝斯','log'],
'note.bd' : ['底鼓','stone'], #即basedrum
'note.bell' : ['铃铛/钟琴','gold_block'],
'note.bit' : ['比特/“芯片”(方波)','emerald_block'],
'note.chime' : ['管钟','packed_ice'],
'note.cow_bell' : ['牛铃','soul_sand'],
'note.didgeridoo' : ['迪吉里杜管','pumpkin'],
'note.flute' : ['长笛','clay'],
'note.guitar' : ['吉他','wool'],
'note.harp' : ['竖琴/钢琴','concrete'], #任意其他类型的方块皆可
'note.hat' : ['击鼓沿/架子鼓','glass'],
'note.iron_xylophone' : ['“铁木琴”(颤音琴)','iron_block'],
'note.pling' : ['“扣弦”(电钢琴)','glowstone'],
'note.snare' : ['小军鼓','sand'],
'note.xylophone' : ['木琴','bone_block']
}
'''乐器对照表\n
乐器英文:[中文, 对应音符盒下方块名称]
注:方块仅取一个'''
height2note = {
0.5: 0,
0.53: 1,
0.56: 2,
0.6: 3,
0.63: 4,
0.67: 5,
0.7: 6,
0.75: 7,
0.8: 8,
0.84: 9,
0.9: 10,
0.94: 11,
1.0: 12,
1.05: 13,
1.12: 14,
1.2: 15,
1.25: 16,
1.33: 17,
1.4: 18,
1.5: 19,
1.6: 20,
1.7: 21,
1.8: 22,
1.9: 23,
2.0: 24,
}
'''音高对照表\n
MC音高:音符盒音调'''

View File

@@ -1,72 +0,0 @@
从此日志开始,我的世界函数音乐构建更名为 函数音创 NoteFunCreater谐音NotFun[狗头]版本号更为0.1.0开始
注意,运行此文件需要第三方库:
1. mido 用于对midi文件的解码
2. py7zr 用于对7z压缩包的压缩与解压等需pycparser, cffi, texttable, pyzstd, pyppmd, pycryptodomex, multivolumefile, brotli, bcj-cffi支持 -(从0.1.3开始不需要)
3. zipfile 用于自动生成函数包的压缩
4. pystray 用于支持窗口任务栏
5. pillow 相当于Python2的PIL用于绘图
0.1.0
2021 7 10 - 2021 7 12
1.程序窗口化
2.仅支持基本的菜单操作
3.程序文件皆储存至其相应目录下
4.程序./bin/目录下文件将会自动防修改
5.删除了彩蛋
0.1.1
2021 7 14
1.新增版本辨别的提示
2.窗口中显示歌曲信息
0.1.2
2021 7 14 - 2021 7 15
1.在没运行过的机器上会自动安装库
2.从midi导入时不会删除其他音轨
3.改进UI样式
4.支持对于单个音轨设置的修改以及音乐主设置的修改
5.当未保存便退出时,会询问存储
6.新增加载进度提示
0.1.3
2021 7 15 - 2021 7 19
1.不再从文件中读取音符及乐器信息(所以包更小了)
2.改进UI
3.修复了修改玩家选择器时变更了音乐标题的bug
4.新增删除当前选定音轨按钮
5.新增重置设置按钮(将音乐总设置设置为开始时的设置)
6.运用多线程加载函数与文件等,程序运行效率更高
7.修复变量作用域混淆问题
0.1.3.1
2021 7 19
1.修复了菜单中无法退出程序的问题
0.1.4
2021 7 22
1.支持显示指令于列表中
TO-DO
1.支持从midi文件的元信息中收取音符信息并自动生成
2.支持生成zip函数包
3.支持使用WebSocket接口自动播放已编辑的音乐
4.可以编辑多个项目
5.能够自动将一个长串的音乐分成多个函数文件
6.支持用户导入自己的乐器
7.支持汇报崩溃记录(通过邮件附件的方式)
8.支持播放字幕
9.支持任务栏角标与通知
10.将控制台版本的彩蛋移植到此版本,开启了任务栏
11.可编辑音符

View File

@@ -1,36 +0,0 @@
世界音创(NoteMapCreater)是金羿开发的一款用于生成我的世界中各类有关音乐的物件的软件
软件禁止商用,源代码始终公开,如使用未经授权的音乐经过此软件生成的任何物件侵犯了他人权利与本软件及其作者无关
Copyright © W-YI 2021
开头,特别感谢:
KCINE提供Cinemusicedit函数包(虽然函数包没怎么用过)
Charlie_Ping提供MusiCreaterBot(音乐地图生成QQ机器人)源码核心以及时不时的催更(虽然源码没有抄)
金羿(作者本人)提供NoteFunCreater(函数音创)的制作经验以及时不时的摸鱼(虽然不是很支持函数音创)
广大群友:高效的催更作业让我以蜗牛的速度前进
Alpha 0.0.0
2021 8 1 - 2021 8 10
1.确定了大概的功能
2.不支持无参数传入
3.可以查看帮助,但是帮助大多功能没实现
4.可以从格式文本、midi文件、钢琴声音MP3导入音轨
5.可以生成一些方块到世界里,但是没有播放器(半支持bw开关)
5.提供了修改文件地址的方法,但是不能修改
Alpha 0.0.1
2021 8 10
1.可以从函数音创的工程文件读取音轨
2.可以新建一个空白世界来生成
3.支持修改输出文件地址
4.支持修改输出方块起始位置
5.支持指定播放乐器,执行实体,执行积分板,播放玩家选择器
6.可以生成指令音乐地图(完全支持-w开关)
Beta 0.0.0
2021 8 X?
1.除了-nw 和 -f 开关不支持以外都支持了
Beta 0.0.1
2021 8 19
1.修复了大量bug

View File

@@ -1,320 +0,0 @@
"""音创系列的音符对照表 以及一系列常数"""
notes = {
'....A' : [0.074, 27.5, 'wood', 8],
'....A#' : [0.0787, 29.135, 'wood', 9],
'....B' : [0.083, 30.868, 'wood', 10],
'...C' : [0.088, 32.703, 'wood', 11],
'...C#' : [0.094, 34.648, 'wood', 12],
'...D' : [0.1, 36.708, 'wood', 13],
'...D#' : [0.105, 38.891, 'log', 0],
'...E' : [0.11, 41.203, 'log', 1],
'...F' : [0.12, 43.654, 'log', 2],
'...F#' : [0.125, 46.249, 'wood', 0],
'...G' : [0.13, 48.999, 'wood', 1],
'...G#' : [0.14, 51.913, 'wood', 2],
'...A' : [0.15, 55.0, 'wood', 3],
'...A#' : [0.16, 58.27, 'wood', 4],
'...B' : [0.17, 61.735, 'wood', 5],
'..C' : [0.18, 65.406, 'wool', 0],
'..C#' : [0.19, 69.296, 'wool', 1],
'..D' : [0.2, 73.416, 'wool', 2],
'..D#' : [0.21, 77.782, 'wool', 3],
'..E' : [0.22, 82.407, 'wool', 4],
'..F' : [0.235, 87.307, 'wool', 5],
'..F#' : [0.25, 92.499, 'concretepowder', 0],
'..G' : [0.26, 97.999, 'concretepowder', 1],
'..G#' : [0.28, 103.826, 'concretepowder', 2],
'..A' : [0.3, 110.0, 'concretepowder', 3],
'..A#' : [0.31, 116.541, 'concretepowder', 4],
'..B' : [0.33, 123.471, 'concretepowder', 5],
'.C' : [0.35, 130.813, 'concretepowder', 6],
'.C#' : [0.37, 138.591, 'concretepowder', 7],
'.D' : [0.4, 146.832, 'concretepowder', 8],
'.D#' : [0.42, 155.563, 'concretepowder', 9],
'.E' : [0.44, 164.814, 'concretepowder', 10],
'.F' : [0.47, 174.614, 'concretepowder', 11],
'.F#' : [0.5, 184.997, 'concretepowder', 12],
'.G' : [0.53, 195.998, 'concretepowder', 13],
'.G#' : [0.56, 207.652, 'concretepowder', 14],
'.A' : [0.6, 220.0, 'concretepowder', 15],
'.A#' : [0.63, 233.082, 'concrete', 0],
'.B' : [0.67, 246.942, 'concrete', 1],
'C' : [0.7, 261.626, 'concrete', 2],
'C#' : [0.75, 277.183, 'concrete', 3],
'D' : [0.8, 293.665, 'concrete', 4],
'D#' : [0.84, 311.127, 'concrete', 5],
'E' : [0.9, 329.628, 'concrete', 6],
'F' : [0.94, 349.228, 'concrete', 7],
'F#' : [1.0, 369.994, 'concrete', 8],
'G' : [1.05, 391.995, 'concrete', 9],
'G#' : [1.12, 415.305, 'concrete', 10],
'A' : [1.2, 440.0, 'concrete', 11],
'A#' : [1.25, 466.164, 'concrete', 12],
'B' : [1.33, 493.883, 'concrete', 13],
'`C' : [1.4, 523.251, 'concrete', 14],
'`C#' : [1.5, 554.365, 'concrete', 15],
'`D' : [1.6, 587.33, 'stained_hardened_clay', 0],
'`D#' : [1.7, 622.254, 'stained_hardened_clay', 1],
'`E' : [1.8, 659.255, 'stained_hardened_clay', 2],
'`F' : [1.9, 698.456, 'stained_hardened_clay', 3],
'`F#' : [2.0, 739.989, 'stained_hardened_clay', 4],
'`G' : [2.1, 783.991, 'stained_hardened_clay', 5],
'`G#' : [2.24, 830.609, 'stained_hardened_clay', 6],
'`A' : [2.4, 880.0, 'stained_hardened_clay', 7],
'`A#' : [2.5, 932.328, 'stained_hardened_clay', 8],
'`B' : [2.67, 987.767, 'stained_hardened_clay', 9],
'``C' : [2.83, 1046.502, 'stained_hardened_clay', 10],
'``C#' : [3.0, 1108.731, 'stained_hardened_clay', 11],
'``D' : [3.17, 1174.659, 'stained_hardened_clay', 12],
'``D#' : [3.36, 1244.508, 'stained_hardened_clay', 13],
'``E' : [3.56, 1318.51, 'stained_hardened_clay', 14],
'``F' : [3.78, 1396.913, 'stained_hardened_clay', 15],
'``F#' : [4.0, 1479.978, 'white_glazed_terracotta', 0],
'``G' : [4.24, 1567.982, 'orange_glazed_terracotta', 0],
'``G#' : [4.5, 1661.219, 'magenta_glazed_terracotta', 0],
'``A' : [4.76, 1760.0, 'light_blue_glazed_terracotta', 0],
'``A#' : [5.04, 1864.655, 'yellow_glazed_terracotta', 0],
'``B' : [5.34, 1975.533, 'lime_glazed_terracotta', 0],
'```C' : [5.66, 2093.005, 'pink_glazed_terracotta', 0],
'```C#' : [6.0, 2217.461, 'gray_glazed_terracotta', 0],
'```D' : [6.35, 2349.318, 'silver_glazed_terracotta', 0],
'```D#' : [6.73, 2489.016, 'cyan_glazed_terracotta', 0],
'```E' : [7.13, 2637.02, 'purple_glazed_terracotta', 0],
'```F' : [7.55, 2793.826, 'blue_glazed_terracotta', 0],
'```F#' : [8.0, 2959.955, 'brown_glazed_terracotta', 0],
'```G' : [8.47, 3135.963, 'green_glazed_terracotta', 0],
'```G#' : [8.98, 3322.438, 'red_glazed_terracotta', 0],
'```A' : [9.51, 3520.0, 'black_glazed_terracotta', 0],
'```A#' : [10.08, 3729.31, 'stained_glass', 0],
'```B' : [10.68, 3951.066, 'stained_glass', 1],
'````C' : [11.31, 4186.009, 'stained_glass', 2],
'0' : [0.0, 0.0, 'glass', 0]
}
'''音符对照表\n
音符:[MC音调, 声音频率, 方块名称, 数据值]'''
#方块
'''
blocks = {
0.074 : ['stained_glass', 3],
0.0787 : ['stained_glass', 4],
0.083 : ['stained_glass', 5],
0.088 : ['stained_glass', 6],
0.094 : ['stained_glass', 7],
0.1 : ['stained_glass', 8],
0.105 : ['stained_glass', 9],
0.11 : ['stained_glass', 10],
0.12 : ['stained_glass', 11],
0.125 : ['stained_glass', 12],
0.13 : ['stained_glass', 13],
0.14 : ['stained_glass', 14],
0.15 : ['stained_glass', 15],
0.16 : ['wool', 0],
0.17 : ['wool', 1],
0.18 : ['wool', 2],
0.19 : ['wool', 3],
0.2 : ['wool', 4],
0.21 : ['wool', 5],
0.22 : ['wool', 6],
0.235 : ['wool', 7],
0.25 : ['concretepowder', 0],
0.26 : ['concretepowder', 1],
0.28 : ['concretepowder', 2],
0.3 : ['concretepowder', 3],
0.31 : ['concretepowder', 4],
0.33 : ['concretepowder', 5],
0.35 : ['concretepowder', 6],
0.37 : ['concretepowder', 7],
0.4 : ['concretepowder', 8],
0.42 : ['concretepowder', 9],
0.44 : ['concretepowder', 10],
0.47 : ['concretepowder', 11],
0.5 : ['concretepowder', 12],
0.53 : ['concretepowder', 13],
0.56 : ['concretepowder', 14],
0.6 : ['concretepowder', 15],
0.63 : ['concrete', 0],
0.67 : ['concrete', 1],
0.7 : ['concrete', 2],
0.75 : ['concrete', 3],
0.8 : ['concrete', 4],
0.84 : ['concrete', 5],
0.9 : ['concrete', 6],
0.94 : ['concrete', 7],
1.0 : ['concrete', 8],
1.05 : ['concrete', 9],
1.12 : ['concrete', 10],
1.2 : ['concrete', 11],
1.25 : ['concrete', 12],
1.33 : ['concrete', 13],
1.4 : ['concrete', 14],
1.5 : ['concrete', 15],
1.6 : ['stained_hardened_clay', 0],
1.7 : ['stained_hardened_clay', 1],
1.8 : ['stained_hardened_clay', 2],
1.9 : ['stained_hardened_clay', 3],
2.0 : ['stained_hardened_clay', 4],
2.1 : ['stained_hardened_clay', 5],
2.24 : ['stained_hardened_clay', 6],
2.4 : ['stained_hardened_clay', 7],
2.5 : ['stained_hardened_clay', 8],
2.67 : ['stained_hardened_clay', 9],
2.83 : ['stained_hardened_clay', 10],
3.0 : ['stained_hardened_clay', 11],
3.17 : ['stained_hardened_clay', 12],
3.36 : ['stained_hardened_clay', 13],
3.56 : ['stained_hardened_clay', 14],
3.78 : ['stained_hardened_clay', 15],
4.0 : ['stained_glass_pane', 0],
4.24 : ['stained_glass_pane', 1],
4.5 : ['stained_glass_pane', 2],
4.76 : ['stained_glass_pane', 3],
5.04 : ['stained_glass_pane', 4],
5.34 : ['stained_glass_pane', 5],
5.66 : ['stained_glass_pane', 6],
6.0 : ['stained_glass_pane', 7],
6.35 : ['stained_glass_pane', 8],
6.73 : ['stained_glass_pane', 9],
7.13 : ['stained_glass_pane', 10],
7.55 : ['stained_glass_pane', 11],
8.0 : ['stained_glass_pane', 12],
8.47 : ['stained_glass_pane', 13],
8.98 : ['stained_glass_pane', 14],
9.51 : ['stained_glass_pane', 15],
10.08 : ['stained_glass', 0],
10.68 : ['stained_glass', 1],
11.31 : ['stained_glass', 2],
0.0 : ['glass', 0]
}
#向查理平致敬!!!!!
'''
Blocks = {
0.074: 'barrel',
0.0787: 'beacon',
0.083: 'bedrock',
0.088: 'black_glazed_terracotta',
0.094: 'blast_furnace',
0.1: 'blue_glazed_terracotta',
0.105: 'blue_ice',
0.11: 'bone_block',
0.12: 'bookshelf',
0.125: 'brick_block',
0.13: 'brown_glazed_terracotta',
0.14: 'cartography_table',
0.15: 'carved_pumpkin',
0.16: 'clay',
0.17: 'coal_block',
0.18: 'coal_ore',
0.19: 'cobblestone',
0.2: 'concrete',
0.21: 'crafting_table',
0.22: 'cyan_glazed_terracotta',
0.235: 'diamond_block',
0.25: 'diamond_ore',
0.26: 'white_glazed_terracotta',
0.28: 'dispenser',
0.3: 'dried_kelp_block',
0.31: 'dropper',
0.33: 'emerald_block',
0.35: 'emerald_ore',
0.37: 'end_bricks',
0.4: 'end_stone',
0.42: 'fletching_table',
0.44: 'furnace',
0.47: 'glass',
0.5: 'glowingobsidian',
0.53: 'glowstone',
0.56: 'gold_block',
0.6: 'gold_ore',
0.63: 'grass',
0.67: 'gray_glazed_terracotta',
0.7: 'green_glazed_terracotta',
0.75: 'hardened_clay',
0.8: 'hay_block',
0.84: 'iron_block',
0.9: 'iron_ore',
0.94: 'jukebox',
1.0: 'lapis_block',
1.05: 'lapis_ore',
1.12: 'light_blue_glazed_terracotta',
1.2: 'lime_glazed_terracotta',
1.25: 'lit_pumpkin',
1.33: 'log',
1.4: 'loom',
1.5: 'magenta_glazed_terracotta',
1.6: 'magma',
1.7: 'melon_block',
1.8: 'web',
1.9: 'mossy_cobblestone',
2.0: 'nether_brick',
2.1: 'nether_wart_block',
2.24: 'netherrack',
2.4: 'noteblock',
2.5: 'observer',
2.67: 'obsidian',
2.83: 'orange_glazed_terracotta',
3.0: 'pink_glazed_terracotta',
3.17: 'piston',
3.36: 'planks',
3.56: 'prismarine',
3.78: 'pumpkin',
4.0: 'purple_glazed_terracotta',
4.24: 'purpur_block',
4.5: 'quartz_block',
4.76: 'quartz_ore',
5.04: 'red_glazed_terracotta',
5.34: 'red_nether_brick',
5.66: 'red_sandstone',
6.0: 'redstone_block',
6.35: 'yellow_glazed_terracotta',
6.73: 'sandstone',
7.13: 'stonebrick',
7.55: 'silver_glazed_terracotta',
8.0: 'slime',
8.47: 'smithing_table',
8.98: 'smoker',
9.51: 'smooth_stone',
10.08: 'snow',
10.68: 'soul_sand',
11.31: 'sponge',
0.0: 'stone'
}
'''频率对照表\n
MC音调:方块名称'''
# 乐器
Instuments = {
'note.banjo' : '班卓',
'note.bass' : '低音',
'note.bassattack' : '贝斯',
'note.bd' : '鼓声',
'note.bell' : '铃声',
'note.bit' : '比特',
'note.cow_bell' : '牛铃',
'note.didgeridoo' : '迪吉',
'note.flute' : '长笛',
'note.guitar' : '吉他',
'note.harp' : '竖琴',
'note.hat' : '架鼓',
'note.chime' : '钟声',
'note.iron_xylophone' : '铁琴',
'note.pling' : '叮叮',
'note.snare' : '响弦',
'note.xylophone' : '木琴'
}
'''乐器对照表\n
乐器英文:中文
翻译雪莹工坊Fun-Fer'''

View File

@@ -1,17 +0,0 @@
"""提供对于音创系列的日志"""
import datetime,os
#载入日志功能
StrStartTime = str(datetime.datetime.now()).replace(':', '_')[:-7]
'''字符串型的程序开始时间'''
def log(info:str = '',isPrinted:bool = True):
'''将信息连同当前时间载入日志'''
if not os.path.exists('./log/'):
os.makedirs('./log/')
with open('./log/'+StrStartTime+'.msct.log', 'a',encoding='UTF-8') as f:
f.write(str(datetime.datetime.now())[11:19]+' '+info+'\n')
if isPrinted:
print(str(datetime.datetime.now())[11:19]+' '+info)

View File

@@ -1,87 +0,0 @@
"""音创系列的文件读取功能"""
from musicreater.nmcsup.log import log
from musicreater.nmcsup.const import notes
#从格式文本文件读入一个音轨并存入一个列表
def ReadFile(fn : str) -> list:
from musicreater.nmcsup.trans import note2list
log('打开'+fn+"并读取音符")
try:
nat = open(fn, 'r', encoding='UTF-8').read().split(" ")
del fn
except:
log("找不到读取目标文件")
return False
Notes = []
log(str(nat)+"已读取")
for i in range(int(len(nat)/2)):
Notes.append([nat[i*2], float(nat[i*2+1])])
Notes = note2list(Notes)
log('音符数据更新'+str(Notes))
return [Notes,]
#从midi读入多个音轨返回多个音轨列表
def ReadMidi(midfile : str ) -> list:
import mido
from musicreater.msctspt.threadOpera import NewThread
Notes = []
try:
mid = mido.MidiFile(midfile)
except:
log("找不到文件或无法读取文件"+midfile)
return False
# 解析
ks = list(notes.values())
def loadMidi(track):
datas = []
for i in track:
if i.is_meta:
log('元信息'+str(i))
pass # 不处理元信息
elif 'note_on' in str(i):
msg = str(i).replace("note=", '').replace("time=", '').split(" ")
log('音符on消息处理后'+str(msg))
if msg[4] == '0':
datas.append([ks[int(msg[2])-20][0], 1.0])
log('延续时间0tick--:添加音符'+str([ks[int(msg[2])-20][0], 1.0]))
else:
datas.append([ks[int(msg[2])-20][0], float(msg[4])/480])
log('延续时间'+msg[4]+'tick--:添加音符' +str([ks[int(msg[2])-20][0], float(msg[4])/480]))
del msg
log('音符增加'+str(datas))
return datas
for j, track in enumerate(mid.tracks):
th = NewThread(loadMidi,(track,))
th.start()
Notes.append(th.getResult())
del ks
return Notes
def ReadOldProject(fn:str) -> list:
import json
from musicreater.nmcsup.trans import note2list
log("读取文件:"+fn)
try:
with open(fn, 'r', encoding='UTF-8') as c:
dataset = json.load(c)
except:
print('找不到文件:'+fn+",请查看您是否输入正确")
log("丢失"+fn)
return False
for i in range(len(dataset['musics'])):
dataset['musics'][i]['notes'] = note2list(dataset['musics'][i]['notes'])
#返回 音轨列表 选择器
return dataset

View File

@@ -1,254 +0,0 @@
"""音创系列的转换功能"""
from nmcsup.log import log
# 输入一个列表 [ [str, float ], [], ... ] 音符str 值为持续时间float
def note2list(Notes : list) -> list:
from musicreater.nmcsup.const import notes
def change(base):
enwo = {
'a': 'A',
'b': 'B',
'c': 'C',
'd': "D",
"e": "E",
'f': 'F',
'g': "G"
}
nuwo = {
'6': 'A',
'7': 'B',
'1': 'C',
'2': "D",
"3": "E",
'4': 'F',
'5': "G"
}
for k, v in enwo.items():
if k in base:
base = base.replace(k, v)
for k, v in nuwo.items():
if k in base:
base = base.replace(k, v)
return base
res = []
log(" === 音符列表=>音调列表")
for i in Notes:
s2 = change(i[0])
log(' === 正在操作音符'+i[0]+'->'+s2)
if s2 in notes.keys():
log(" === 找到此音符,加入:"+str(notes[s2][0]))
res.append([notes[s2][0], float(i[1])])
else:
log(' === '+s2+'不在音符表内,此处自动替换为 休止符0 ')
res.append(['0', float(i[1])])
log(' === 最终反回'+str(res))
return res
def mcnote2freq(Notes):
from musicreater.nmcsup.const import notes
mcnback = {}
for i,j in notes.items():
mcnback[j[0]] = i
res = []
log(" === 我的世界音调表=>频率列表")
for i in Notes:
log(' === 正在操作音符'+i[0]+'->'+mcnback[i[0]])
res.append([notes[mcnback[i[0]]][1], float(i[1])])
log(' === 最终反回'+str(res))
return res
#MP3文件转midi文件
def Mp32Mid(mp3File, midFile):
from piano_transcription_inference import PianoTranscription, sample_rate, load_audio
# 加载
(audio, _) = load_audio(mp3File, sr=sample_rate, mono=True)
# 实例化并转换
PianoTranscription(device="cpu").transcribe(audio, midFile)
#传入一个音符列表转为指令列表
def Note2Cmd(Notes : list,ScoreboardName:str,Instrument:str, PlayerSelect:str='',isProsess:bool=False) -> list:
commands = []
a = 0.0
if isProsess:
length = len(Notes)
j = 1
for i in range(len(Notes)):
commands.append("execute @a"+PlayerSelect+" ~ ~ ~ execute @s[scores={"+ScoreboardName+"="+str(int((a+2)*5+int(Notes[i][1]*5)))+"}] ~ ~ ~ playsound "+Instrument+" @s ~ ~ ~ 1000 "+str(Notes[i][0])+" 1000\n")
a += Notes[i][1]
if isProsess:
commands.append("execute @a"+PlayerSelect+" ~ ~ ~ execute @s[scores={"+ScoreboardName+"="+str(int((a+2)*5+int(Notes[i][1]*5)))+"}] ~ ~ ~ title @s actionbar §e▶ 播放中: §a"+str(j)+"/"+str(length)+" || "+str(int(j/length*1000)/10)+"\n")
j+=1
commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI金羿\n")
return commands
import amulet
import amulet_nbt
from amulet.api.block import Block
from amulet.api.block_entity import BlockEntity
from amulet.utils.world_utils import block_coords_to_chunk_coords
from amulet_nbt import TAG_String,TAG_Compound,TAG_Byte
#简单载入方块
#level.set_version_block(posx,posy,posz,"minecraft:overworld",("bedrock", (1, 16, 20)),Block(namespace, name))
#转入指令列表与位置信息转至世界
def Cmd2World(cmd:list,world:str,dire:list):
'''将指令以命令链的形式载入世界\n
cmd指令列表位为一个序列中包含指令字符串\n
world为地图所在位置需要指向文件夹dire为指令方块生成之位置'''
level = amulet.load_level(world)
cdl = []
for i in cmd:
try:
if (i[:i.index('#')].replace(' ','') != '\n') and(i[:i.index('#')].replace(' ','') != ''):
cdl.append(i[:i.index('#')])
except:
cdl.append(i)
i = 0
#第一个是特殊
universal_block = Block('universal_minecraft','command_block',{'conditional':TAG_String("false"),'facing':TAG_String('up'),'mode':TAG_String("repeating")})
cx, cz = block_coords_to_chunk_coords(dire[0], dire[2])
chunk = level.get_chunk(cx, cz, "minecraft:overworld")
offset_x, offset_z = dire[0] - 16 * cx, dire[2] - 16 * cz
universal_block_entity = BlockEntity( 'universal_minecraft','command_block',dire[0],dire[1],dire[2],amulet_nbt.NBTFile(TAG_Compound({'utags': TAG_Compound({'auto': TAG_Byte(0),'Command': TAG_String(cdl.pop(0))}) })))
chunk.blocks[offset_x, dire[1], offset_z] = level.block_palette.get_add_block(universal_block)
chunk.block_entities[(dire[0], dire[1], dire[2])] = universal_block_entity
chunk.changed = True
#集体上移
dire[1]+=1;
#真正开始
down = False
for j in cdl:
if dire[1]+i >= 255:
dire[0]+=1
i=0
down = not down
#定义此方块
if dire[1]+i == 254 :
universal_block = Block('universal_minecraft','command_block',{'conditional':TAG_String("false"),'facing':TAG_String('east'),'mode':TAG_String("chain")})
else:
if down:
universal_block = Block('universal_minecraft','command_block',{'conditional':TAG_String("false"),'facing':TAG_String('down'),'mode':TAG_String("chain")})
else:
universal_block = Block('universal_minecraft','command_block',{'conditional':TAG_String("false"),'facing':TAG_String('up'),'mode':TAG_String("chain")})
cx, cz = block_coords_to_chunk_coords(dire[0], dire[2])
#获取区块
chunk = level.get_chunk(cx, cz, "minecraft:overworld")
offset_x, offset_z = dire[0] - 16 * cx, dire[2] - 16 * cz
if down:
#定义方块实体
universal_block_entity = BlockEntity( 'universal_minecraft','command_block',dire[0],254-i,dire[2],amulet_nbt.NBTFile(TAG_Compound({'utags': TAG_Compound({'auto': TAG_Byte(1),'Command': TAG_String(j)}) })))
#将方块加入世界
chunk.blocks[offset_x, 254-i, offset_z] = level.block_palette.get_add_block(universal_block)
chunk.block_entities[(dire[0], 254-i, dire[2])] = universal_block_entity
else:
#定义方块实体
universal_block_entity = BlockEntity( 'universal_minecraft','command_block',dire[0],dire[1]+i,dire[2],amulet_nbt.NBTFile(TAG_Compound({'utags': TAG_Compound({'auto': TAG_Byte(1),'Command': TAG_String(j)}) })))
#将方块加入世界
chunk.blocks[offset_x, dire[1]+i, offset_z] = level.block_palette.get_add_block(universal_block)
chunk.block_entities[(dire[0], dire[1]+i, dire[2])] = universal_block_entity
#设置为已更新区块
chunk.changed = True
i+=1
del i, cdl
#保存世界并退出
level.save()
level.close()
#音符转成方块再加载到世界里头
def Blocks2World(world:str,dire:list,Datas:list):
from musicreater.nmcsup.const import Blocks
level = amulet.load_level(world)
i = 0
def setblock(block:str,pos:list):
'''pos : list[int,int,int]'''
cx, cz = block_coords_to_chunk_coords(pos[0], pos[2])
chunk = level.get_chunk(cx, cz, "minecraft:overworld")
offset_x, offset_z = pos[0] - 16 * cx, pos[2] - 16 * cz
chunk.blocks[offset_x, pos[1], offset_z] = level.block_palette.get_add_block(Block("minecraft",block))
chunk.changed = True
for j in Datas:
if dire[1]+1 >= 255:
i = 0
dire[0]+=1
setblock(Blocks[j[0]],[dire[0],dire[1]+i,dire[2]])
i = int(i+j[1]+0.5) #四舍五入
level.save()
level.close()
#传入音符列表制作播放器指令
def Notes2Player(Note,dire:list,CmdData:dict):
'''传入音符列表、坐标、指令数据,生成播放器指令'''
Notes = {}
for i in Note:
Notes[i[0]] = ''
Notes = list(Notes.keys())
from musicreater.nmcsup.const import Blocks
Cmds = []
for j in Notes:
Cmds.append('execute @e[x='+str(dire[0])+',y='+str(dire[1])+',z='+str(dire[2])+',dy='+str(255-dire[1])+',name='+CmdData['Ent']+'] ~ ~ ~ detect ~ ~ ~ '+Blocks[j]+' 0 execute @a '+CmdData['Pls']+' ~ ~ ~ playsound '+CmdData['Ins']+' @s ~ ~ ~ 1000 '+str(j)+' 1000\n')
Cmds+=['#本函数由 金羿 音·创 生成\n','execute @e[y='+str(dire[1])+',dy='+str(255-dire[1])+',name='+CmdData['Ent']+'] ~ ~ ~ tp ~ ~1 ~\n','execute @e[y=255,dy=100,name='+CmdData['Ent']+'] ~ ~ ~ tp ~1 '+str(dire[1])+' ~\n','#音·创 开发交流群 861684859']
return Cmds
#传入音符列表生成方块至世界
def Datas2BlkWorld(NoteData,world:str,dire:list):
for i in range(len(NoteData)):
Blocks2World(world,[dire[0],dire[1],dire[2]+i],NoteData[i])

View File

@@ -1,89 +0,0 @@
"""音创系列版本号和版本操作函数"""
from musicreater.msctspt.bugReporter import version
#以下下两个值请在 msctspt/bugReporter 的version类中修改
VER = version.version
'''当前版本'''
LIBS = version.libraries
'''当前所需库'''
#判断版本、临时文件与补全库
def compver(ver1, ver2):
"""
传入不带英文的版本号,特殊情况:"10.12.2.6.5">"10.12.2.6"
:param ver1: 版本号1
:param ver2: 版本号2
:return: ver1< = >ver2返回-1/0/1
"""
list1 = str(ver1).split(".")
list2 = str(ver2).split(".")
# 循环次数为短的列表的len
for i in range(len(list1)) if len(list1) < len(list2) else range(len(list2)):
if int(list1[i]) == int(list2[i]):
pass
elif int(list1[i]) < int(list2[i]):
return -1
else:
return 1
# 循环结束,哪个列表长哪个版本号高
if len(list1) == len(list2):
return 0
elif len(list1) < len(list2):
return -1
else:
return 1
#
# ————————————————
# 版权声明上面的函数compver为CSDN博主「基友死得早」的原创文章中的函数遵循CC 4.0 BY-SA版权协议转载请附上原文出处链接及本声明。
# 原文链接https://blog.csdn.net/tinyjm/article/details/93514261
# ————————————————
#
import os
def InstallLibs(now,LIBS):
'''比对库信息并安装库'''
from os import system as run
for i in LIBS:
if not i in now:
print("安装库:"+i)
run("python -m pip install "+i+" -i https://pypi.tuna.tsinghua.edu.cn/simple")
def chkver(ver = VER,libs = LIBS):
'''通过文件比对版本信息并安装库'''
if not os.path.exists(os.getenv('APPDATA')+'\\Musicreater\\msct.ActiveDatas.msct'):
print("新安装库")
os.makedirs(os.getenv('APPDATA')+'\\Musicreater\\')
with open(os.getenv('APPDATA')+'\\Musicreater\\msct.ActiveDatas.msct', 'w') as f:
f.write(ver[0]+'\n')
for i in libs:
f.write(i+'\n')
InstallLibs([],libs)
else:
with open(os.getenv('APPDATA')+'\\Musicreater\\msct.ActiveDatas.msct', 'r') as f:
v = f.readlines()
cp = compver(ver[0], v[0])
if cp != 0:
InstallLibs(v[1:],libs)
with open(os.getenv('APPDATA')+'\\Musicreater\\msct.ActiveDatas.msct', 'w') as f:
f.write(ver[0]+'\n')
for i in libs:
f.write(i+'\n')
del cp
def resetver():
'''重置版本信息'''
import shutil
shutil.rmtree(os.getenv('APPDATA')+'\\Musicreater\\')

View File

@@ -1,11 +0,0 @@
LANGUAGE = {
'main':{
"name":"音·创",
"version":"当前版本",
"run":"执行指令",
},
'command':{
"NotAvailable":"此指令不可用。",
"FormatError":"指令格式错误,请查看 命令行操作.md 以查阅指令。"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 441 KiB

View File

@@ -1,11 +0,0 @@
生命灵动 当用激情跃起奋发之力
奇偶数阵
学海无涯 应用爱意徜徉
在生命的起源寻找灵魂的慰藉
纪念那一段辉煌灿烂的青春年华
以梦想为驱使 创造属于自己的未来
集青春之力 绽放爱意之花
那个曾与我相伴的人 依稀在我的心头留恋
我爱你 我 爱 你
你是我灵魂中绽放出最艳丽的花朵
心之所向 意之所属

1
trans_mid_analyse.bat Normal file
View File

@@ -0,0 +1 @@
pyside6-uic mid_analyse.ui -o mid_analyse.py

15
update.sh Normal file
View File

@@ -0,0 +1,15 @@
rm -rf ./MusictraterPkgver
git clone https://gitee.com/EillesWan/Musicreater.git -b pkgver MusictraterPkgver
cd ./MusictraterPkgver
python3 -O -m compileall -b .
find . -name "*.py"|xargs rm -rf
find . -name "__pycache__" |xargs rm -rf
rm -rf ./.git
rm ./.gitignore

View File

@@ -1,34 +0,0 @@
# Musicreater 音·创 命令行模式
为了对后期安卓的兼容,先支持命令行
## 命令列表
### exit \[/s\] \[/c\]
- ```/s``` 保存并退出
- ```/c``` 清除日志
### save \[/a \<fileName\>\]
- ```/a <文件名>``` 指定文件名保存
### load \[/\<loadMethod: input|txt|mid\> \<text|fileName\>\]
- ```/input <文本>``` 输入音符
- ```/txt <文件名>``` 从文本载入音符
- ```/mid <文件名>``` 解析midi文件载入音符
### win
- 开启窗口模式的 音·创(仅支持的系统下有效)
### chdir \<direction\>
- 切换当前工作目录
### build \[/\<buildMethod: file|directory|mcpack\> \<direction\>\]
- ```/file <目录位置>``` 在指定目录生成函数文件(散装)
- ```/directory <目录位置>``` 在指定目录生成一个附加包目录
- ```/mcpack <目录位置>``` 在指定目录生成一个.mcpack附加包

View File

@@ -1,29 +0,0 @@
# -*- conding: utf8 -*-
import os
from src.musicreater.msctspt.funcOpera import keepart
l = 0
for path,dir_list,file_list in os.walk(r"./") :
for file_name in file_list:
if keepart(file_name,'.',None) == '.py':
file = os.path.join(path, file_name)
print("得到文件名:"+str(file))
for i in open(file,'r',encoding="utf-8"):
code = i.replace(' ','').replace('\n','')
try:
code -= code[code.index('#'):]
except:
pass;
if code:
print("\t"+code)
l+=1
else:
pass;
input("\n最终代码行数为:"+str(l))

View File

@@ -1,224 +0,0 @@
{
"mainset": {
"PackName": "RyounTeamSong",
"MusicTitle": "RyounUp",
"IsRepeat": false,
"PlayerSelect": ""
},
"musics": [
{
"set": {
"EntityName": "MusicSupport",
"ScoreboardName": "MusicSupport",
"Instrument": "harp",
"FileName": "RyounUp_RyounTeamSong"
},
"notes": [
[
".5",
1.0
],
[
"1",
1.0
],
[
"1",
1.0
],
[
"3",
1.5
],
[
"3",
0.5
],
[
"2",
1.5
],
[
"1",
0.5
],
[
"2",
1.0
],
[
"5",
1.0
],
[
"3",
1.5
],
[
"2",
0.5
],
[
".6",
1.0
],
[
".5",
1.0
],
[
"3",
1.5
],
[
"2",
0.5
],
[
"1",
1.0
],
[
"5",
1.0
],
[
"5",
1.0
],
[
"6",
0.5
],
[
"5",
0.5
],
[
"3",
1.0
],
[
"5",
0.5
],
[
"3",
0.5
],
[
"2",
1.0
],
[
"2",
1.0
],
[
"3",
0.5
],
[
"2",
0.5
],
[
"1",
1.0
],
[
"1",
1.0
],
[
"3",
1.0
],
[
"3",
1.0
],
[
"5",
1.0
],
[
"0",
1.0
],
[
".5",
0.5
],
[
".6",
0.5
],
[
"1",
1.0
],
[
"1",
1.0
],
[
"6",
1.0
],
[
"1",
1.0
],
[
"2",
1.0
],
[
"3",
1.0
],
[
"3",
1.0
],
[
"3",
1.0
],
[
"3",
1.0
],
[
"2",
1.0
],
[
"5",
1.5
],
[
".5",
0.5
],
[
"1",
1.0
],
[
"1",
1.0
],
[
"0",
1.0
],
[
"0",
1.0
]
]
}
]
}

Binary file not shown.

File diff suppressed because one or more lines are too long