diff --git a/AutoInstaller/MSCT Auto Installer b/AutoInstaller/MSCT Auto Installer new file mode 100755 index 0000000..31b5de4 Binary files /dev/null and b/AutoInstaller/MSCT Auto Installer differ diff --git a/AutoInstaller/MSCT Auto Installer.exe b/AutoInstaller/MSCT Auto Installer.exe new file mode 100644 index 0000000..08dc593 Binary files /dev/null and b/AutoInstaller/MSCT Auto Installer.exe differ diff --git a/AutoInstaller/MSCT Auto Installer.py b/AutoInstaller/MSCT Auto Installer.py new file mode 100644 index 0000000..7ae2148 --- /dev/null +++ b/AutoInstaller/MSCT Auto Installer.py @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- + + +# W-YI 金羿 +# QQ 2647547478 +# 音·创 开发交流群 861684859 +# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com +# 版权所有 Team-Ryoun 金羿("Eilles Wan") +# 若需转载或借鉴 请附作者 + + +""" +音·创自动安装器 (Musicreater Auto Installer) +对音·创的自动安装提供支持的独立软件 +Musicreater Auto Installer (音·创自动安装器) +A software that used for installing Musicreater automatically + + Copyright 2022 Team-Ryoun + + 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. +""" + +# 代码写的并非十分的漂亮,还请大佬多多包涵;本软件源代码依照Apache软件协议公开 + + +# 下面为正文 + + +from sys import platform +from platform import architecture +import urllib.request +import zipfile +from os import system as srun +from os import walk, rename, remove, path, chdir, listdir +from shutil import rmtree, move + + +if platform == "win32": + + nowpath = __file__[: len(__file__) - __file__[len(__file__) :: -1].index('\\')] + + if srun('python -V'): + + print('\033[7m{}\033[0m'.format("正在下载python\nDownloading Python")) + + try: + urllib.request.urlretrieve( + "https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe" + if architecture()[0] == "32bit" + else "https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe", + "./pythonInstaller.exe", + ) + # urllib.request.urlretrieve("https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe","./pythonInstaller.exe") + except Exception as E: + input(str(E) + "\n自动下载失败,按下回车取消") + exit() + + print('正在安装python\nInstalling Python') + + # open('install.bat','w').write(f'.\\pythonInstaller.exe /passive InstallAllUsers=0 TargetDir="{nowpath}python38" DefaultJustForMeTargetDir="{nowpath}python38" AssociateFiles=0 CompileAll=1 PrependPath=0 Shortcuts=0 Include_doc=0 Include_launcher=0 InstallLauncherAllUsers=0 Include_test=0 Include_tools=0') + + srun( + f'.\\pythonInstaller.exe /passive InstallAllUsers=1 AssociateFiles=1 CompileAll=1 PrependPath=1 Shortcuts=1 Include_doc=0 Include_exe=1 Include_pip=1 Include_lib=1 Include_tcltk=1 Include_launcher=1 InstallLauncherAllUsers=1 Include_test=0 Include_tools=0' + ) + + remove('./pythonInstaller.exe') + + # print('\033[7m{}\033[0m'.format("正在下载pip安装工具\nDownloading get-pip tool")) + + # try: + # urllib.request.urlretrieve( + # "https://bootstrap.pypa.io/get-pip.py", "./python38/get-pip.py" + # ) + # except Exception as E: + # input(str(E) + "\n自动下载失败,按下回车取消") + # exit() + + # print('\033[7m{}\033[0m'.format("正在下载pip\nDownloading pip")) + + # chdir('./python38') + # srun(r'".\python.exe get-pip.py') + + # print('\033[7m{}\033[0m'.format('正在安装pip\nInstalling pip')) + + # for dire in listdir('./Lib/site-packages/'): + # move('./Lib/site-packages/'+dire,'./'+dire) + + # print('\033[7m{}\033[0m'.format("完成!")) + + # chdir('../') + + try: + choseurl = int( + input( + '\033[7m{}\033[0m'.format( + """请选择 音·创 下载源,默认为0 +Please choose a download source of Musicreater(default 0) +[0] 私有服务器<暂无> | Private Server +[1] Gitee +[2] Github\n:""" + ) + ) + ) + except Exception as E: + print('\033[7m{}\033[0m'.format(str(E) + "\n将使用默认源\nUsing default source")) + choseurl = 0 + + myurl = "" + Giteeurl = "https://gitee.com/EillesWan/Musicreater/repository/blazearchive/master.zip?Expires=1647771436&Signature=%2BkqLHwmvzScCd4cPQDP0LHLpqeZUxOrOv17QpRy%2FTzs%3D" + Githuburl = ( + "https://codeload.github.com/EillesWan/Musicreater/zip/refs/heads/master" + ) + + url = ( + myurl + if choseurl == 0 + else Giteeurl + if choseurl == 1 + else Githuburl + if choseurl == 2 + else myurl + ) + + print('\033[7m{}\033[0m'.format("正在下载音·创\nDownloading Musicreater")) + + try: + urllib.request.urlretrieve(url, "./master.zip") + except Exception as E: + input('\033[0{}\033[0m'.format(str(E) + "\n自动下载失败,按下回车取消")) + exit() + + print('\033[7m{}\033[0m'.format("安装音·创\nInstalling Musicreater")) + + zipfile.ZipFile("./master.zip", "r").extractall() + + remove("./master.zip") + + try: + rmtree("./Musicreater") + except: + pass + + rename("./Musicreater-master/", "./Musicreater/") + +elif platform == 'linux': + srun("sudo apt-get install python3") + srun("sudo apt-get install python3-pip") + srun("sudo apt-get install git") + try: + choseurl = int( + input( + '\033[0{}\033[0m'.format( + """请选择 音·创 下载源,默认为1 +Please choose a download source of Musicreater(default 1) +[1] Gitee +[2] Github\n:""" + ) + ) + ) + except Exception as E: + print(str(E) + "\n将使用默认源\nUsing default source") + choseurl = 1 + + url = ( + "https://gitee.com/EillesWan/Musicreater.git" + if choseurl == 1 + else "https://github.com/EillesWan/Musicreater.git" + if choseurl == 2 + else "https://gitee.com/EillesWan/Musicreater.git" + ) + srun(f"sudo git clone {url}") + + +print('\033[7m{}\033[0m'.format("编译音·创\nCompiling Musicreater")) + +if platform == "linux": + srun("python3 -O -m compileall -b ./Musicreater/") +elif platform == "win32": + srun("python -O -m compileall -b ./Musicreater/") + +for parent, dirnames, filenames in walk("./Musicreater"): + for filename in filenames: + if filename[-3:] == ".py": + fn = path.join(parent, filename) + remove(fn) + print(f"删除文件 {fn}") + for dirname in dirnames: + if dirname == "__pycache__": + pn = path.join(parent, dirname) + rmtree(pn) + print(f"删除目录 {pn}") + + +print( + '\033[7m{}\033[0m'.format( + """您可以开始使用音·创了 +我们将在后台为您安装各项支持库 +您可以运行Musicreater文件夹中的Musicreater.pyc文件来运行音·创 + +You can use Musicreater now, +We will setup the libraries ineed for you in background, +You can now open Musicreater.PYC in the directory of ./Musicreater to run Musicreater +""" + ) +) + + +if platform == "linux": + srun("python3 ./Musicreater/补全库.pyc") +elif platform == "win32": + srun("python ./Musicreater/补全库.pyc") diff --git a/LICENSE b/LICENSE index 7060aa2..01813e0 100644 --- a/LICENSE +++ b/LICENSE @@ -176,7 +176,7 @@ END OF TERMS AND CONDITIONS - Copyright 2022 Eilles Wan (金羿) + 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. diff --git a/Musicreater.New.py b/Musicreater.New.py new file mode 100644 index 0000000..ec75b8e --- /dev/null +++ b/Musicreater.New.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- + + +# W-YI 金羿 +# QQ 2647547478 +# 音·创 开发交流群 861684859 +# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com +# 版权所有 Team-Ryoun 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") +# 若需转载或借鉴 请附作者 + + +""" +音·创 (Musicreater) +一款免费开源的 《我的世界:基岩版》 音乐制作软件 +Musicreater (音·创) +A free opensource software which is used for creating all kinds of musics in Minecraft + + Copyright 2022 Team-Ryoun + + 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. +""" + +# 代码写的并非十分的漂亮,还请大佬多多包涵;本软件源代码依照Apache软件协议公开 + + +# 下面为正文 + + + +from msctspt.bugReporter import version + +__ver__ = f'{version.version[1]} {version.version[0]}' +__author__ = '金羿Eilles' + +from msctLib.display import * + +from msctLib.function import * + +from msctLib.data import uniteIO + + +hb = r''' __ __ + /\ \/\ \ + \ \ \_\ \ __ _____ _____ __ __ + \ \ _ \ /'__`\ /\ '__`\ /\ '__`\ /\ \/\ \ + \ \ \ \ \ /\ \L\.\_\ \ \L\ \\ \ \L\ \\ \ \_\ \ + \ \_\ \_\\ \__/.\_\\ \ ,__/ \ \ ,__/ \/`____ \ + \/_/\/_/ \/__/\/_/ \ \ \/ \ \ \/ `/___/> \ + \ \_\ \ \_\ /\___/ + \/_/ \/_/ \/__/ + ____ __ __ __ + /\ _`\ __ /\ \__ /\ \ /\ \ + \ \ \L\ \ /\_\ _ __ \ \ ,_\\ \ \___ \_\ \ __ __ __ + \ \ _ <'\/\ \ /\`'__\\ \ \/ \ \ _ `\ /'_` \ /'__`\ /\ \/\ \ + \ \ \L\ \\ \ \\ \ \/ \ \ \_ \ \ \ \ \ /\ \L\ \ /\ \L\.\_\ \ \_\ \ + \ \____/ \ \_\\ \_\ \ \__\ \ \_\ \_\\ \___,_\\ \__/.\_\\/`____ \ + \/___/ \/_/ \/_/ \/__/ \/_/\/_/ \/__,_ / \/__/\/_/ `/___/> \ + /\___/ + \/__/ ''' + + + +def __main__(): + import datetime,time,random,os,sys,zhdate + if datetime.date.today().month == 4 and datetime.date.today().day == 3: + if sys.platform == 'win32': + os.system('color 4e') + os.system('cls') + for i in range(len(hb)): + print(hb[i], end='', flush=True) + time.sleep(random.random() * 0.001) + input("金羿 生日快乐!") + elif '三月初五' in zhdate.ZhDate.today().chinese(): + input('缅怀先祖 祭祀忠勇 勿忘国耻 振兴中华') + + else: + disp() + + + + + + + + + +if __name__ == '__main__': + __main__() \ No newline at end of file diff --git a/Musicreater.py b/Musicreater.py index d3dc43c..b892c02 100644 --- a/Musicreater.py +++ b/Musicreater.py @@ -1,1995 +1,2005 @@ -# -*- coding: utf-8 -*- -# ! python3 - - -# W-YI 金羿 -# QQ 2647547478 -# 音·创 开发交流群 861684859 -# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com -# 版权所有 Team-Ryoun 金羿 -# 若需转载或借鉴 请附作者 - - -""" - Copyright 2022 Eilles Wan (金羿) - - 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. -""" - -# 代码写的并非十分的漂亮,还请大佬多多包涵;本软件源代码依照Apache软件协议公开 - -# -----------------------------分割线----------------------------- -# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日 -# 统计:致命(三级)错误:0个;警告(二级)错误:15个;语法(一级)错误:597个 -# 目前我的Pycharm并没有显示任何错误,有错误可以向 -# bgArray 诸葛亮与八卦阵 -# QQ 474037765 或最好加入:音·创 开发交流群 861684859 -# ------------------------- split line----------------------------- -# Zhuge Liang and Bagua array help to modify the grammar date: -- January 19, 2022 -# Statistics: fatal (Level 3) errors: 0; Warning (Level 2) errors: 15; Syntax (Level 1) error: 597 -# At present, my Pycham does not display any errors. If there are errors, you can report them to me -# Bgarray Zhuge Liang and Bagua array -# QQ 474037765 or better join: Musicreater development exchange group 861684859 -# ------------------------- split line----------------------------- - -# 下面为正文 - - -import json -import os -import shutil -import sys -import threading -import pickle -import tkinter as tk -import tkinter.filedialog -import tkinter.messagebox -import tkinter.simpledialog - -from languages.lang import * -from msctspt.threadOpera import NewThread -from nmcsup.vers import VER - -__version__ = VER[1] + VER[0] -__author__ = 'W-YI (金羿)' -dire = "" -begp = "" -endp = "" - -print('建立变量,存入内存,载入字典常量函数') - -# 主体部分 - -# 支持多文件同时操作 - -# dataset[{ 'mainset':{ 'x':'y' }, 'musics': [ { 'set' :{ 'A':'B' } , 'note' : [ [ 'a' , b ], ] }, ] }, ] - -# 编辑: -# 修改主设置: dataset[第几个项目]['mainset']['什么设置'] = '设置啥' -# 修改音乐: dataset[第几个项目]['musics'][第几个音轨]['notes'][第几个音符][音符还是时间(0,1)] = 改成啥 -# 修改音轨设置: dataset[第几个项目]['musics'][第几个音轨]['set']['什么设置'] = '设置啥' -# -# 新增音轨: dataset[第几个项目]['musics'].append(datasetmodelpart) -# - - -dataset = [ - { - 'mainset': { - 'ReadMethod': 'old', - 'PackName': 'Ryoun', - 'MusicTitle': 'Noname', - 'IsRepeat': False, - 'PlayerSelect': '' - }, - 'musics': [ - { - 'set': { - 'EntityName': 'MusicSupport', - 'ScoreboardName': 'MusicSupport', - 'Instrument': 'note.harp', - 'FileName': 'Music' - }, - 'notes': [ - - ] - }, - ], - }, -] -'''一个项目中的全部数据。格式参照: -[ - { - 'mainset':{ - 'PackName':'Ryoun', - 'MusicTitle':'Noname', - 'IsRepeat':False, - 'PlayerSelect':'' - }, - 'musics':[ - { - 'set':{ - 'EntityName':'music_support', - 'ScoreboardName':'music_support', - 'Instrument':'harp', - 'FileName':'Music' - }, - 'notes':[ - - Note对象 - 或 - - [MC音调, 持续时间(s)] - ] - }, - ], - }, -] -''' - -is_new_file = True -'''这是否是一个新建的项目?''' - -is_save = True -'''当前项目是否已保存?''' - -ProjectName = '' -'''项目名称,即打开的msct文件名''' - -clearLog = False -'''是否在程序结束时移除日志''' - -NowMusic = 0 -'''当前音轨''' - -root = tk.Tk() -'''主窗口''' - - -def DMM(): # 反回字典用于编辑 - datasetmodelpart = { - 'set': { - 'EntityName': 'MusicSupport', - 'ScoreboardName': 'MusicSupport', - 'Instrument': 'note.harp', - 'FileName': 'Music' - }, - 'notes': [] - } - return datasetmodelpart - - -print('完成') - - -def __main__(): - """音·创 本体\n - W-YI 金羿\n - QQ 2647547478\n - 音·创 开发交流群 861684859\n - Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com\n - 版权所有 Team-Ryoun 金羿\n - 代码根据Apache 2.0 协议开源\n - 若需转载或借鉴 请附作者\n - """ - - print('音·创 正在启动……') - - print('载入日志功能...') - from nmcsup.log import log - from nmcsup.log import end - print('完成!') - - print('更新执行位置...') - if sys.platform == 'win32': - try: - os.chdir(__file__[:len(__file__) - __file__[len(__file__)::-1].index('\\')]) - log('更新执行位置,当前文件位置 {}'.format(__file__)) - except FileNotFoundError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,所以既然是pass就随便填一个错误 - pass - else: - try: - os.chdir(__file__[:len(__file__) - __file__[len(__file__)::-1].index('/')]) - except FileNotFoundError: - pass - log('其他平台:{} 更新执行位置,当前文件位置 {}'.format(sys.platform, __file__)) - print('完成!') - - # 读取文件 - - print('载入文件读取函数') - - def ReadFile(fn: str): # -> list - from nmcsup.nmcreader import ReadFile as fileRead - k = fileRead(fn) - if k is False: - tk.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[105].format(fn)) - return - else: - return k - - # 老的列表读取 - def ReadMidi(midfile: str): # -> str - from nmcsup.nmcreader import ReadMidi as midiRead - k = midiRead(midfile) - if k is False: - tk.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[105].format(midfile)) - return - else: - return k - - # 音色读取 - def LoadMidi(midfile: str): # -> str - from bgArrayLib.reader import midiNewReader - k = midiNewReader(midfile) - if k is False: - tk.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[105].format(midfile)) - return - else: - return k - - # 新的类读取 - def MidiAnalysisClass(midfile: str): - from bgArrayLib.reader import midiClassReader - k = midiClassReader(midfile) - if k is False: - tk.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[105].format(midfile)) - return - else: - return k - - print('完成!') - - # 菜单命令 - print('加载菜单命令...') - - def exitapp(): - global is_save - if is_save is not True: - if tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[106]): - SaveProject() - log('程序正常退出') - - if os.path.isfile("1.pkl"): - os.remove("1.pkl") - - try: - global dataset - del dataset - global root - root.destroy() - del root - except tkinter.TclError: - pass - - if clearLog: - print(READABLETEXT[2]) - # err = True - # try: - end() - if os.path.exists('./log/'): - shutil.rmtree('./log/') - if os.path.exists('./logs/'): - shutil.rmtree('./logs/') - if os.path.exists('./cache/'): - shutil.rmtree('./cache/') - if os.path.exists('./nmcsup/log/'): - shutil.rmtree('./nmcsup/log/') - if os.path.exists('./nmcsup/logs/'): - shutil.rmtree('./nmcsup/logs/') - # err = False - # except: - # print(READABLETEXT[3]) - # - # finally: - # if err is True: - # print(READABLETEXT[3]) - - exit() - - print('退出命令加载完成!') - - def SaveProject(): - global is_save - if is_new_file: - # 新的项目相等于另存为 - SaveAsProject() - return - else: - if dataset[0].get('mainset').get('ReadMethod') == "old": - # 旧项目旧存着吧 - log('存储已有文件:{}'.format(ProjectName)) - with open(ProjectName, 'w', encoding='utf-8') as f: - json.dump(dataset[0], f) - tkinter.messagebox.showinfo(title=READABLETEXT[4], message=READABLETEXT[107].format(ProjectName)) - is_save = True - elif dataset[0].get('mainset').get('ReadMethod') == "class": # 这部分相当SaveClassProject()函数 - # if is_new_file: - # # 新的项目相等于另存为 - # SaveAsClassProject() - # return - # else: - with open(ProjectName, 'wb') as f: - pickle.dump(dataset, f) - tkinter.messagebox.showinfo(title=READABLETEXT[4], - message=READABLETEXT[107].format(ProjectName)) - is_save = True - # return - elif dataset[0].get('mainset').get('ReadMethod') == "new": # 这部分相当于SaveNewProject()函数 - # if is_new_file: # 这部分相当于SaveAsNewProject()函数 - # # 新的项目相等于另存为 - # SaveAsNewProject() - # return - # else: - save_list = [dataset] - try: - with open("1.pkl", 'rb') as r: - save_list.append(pickle.load(r)) - except FileNotFoundError: - pass - with open(ProjectName, 'wb') as f: - pickle.dump(save_list, f) - tkinter.messagebox.showinfo(title=READABLETEXT[4], - message=READABLETEXT[107].format(ProjectName)) - is_save = True - return - - print('保存项目命令加载完成!') - - def SaveAsProject(): - global is_save - if dataset[0].get('mainset').get('ReadMethod') == "old": - # 另存为项目 - fn = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[5], initialdir=r'./', - filetypes=[(READABLETEXT[108][0], '.msct'), - (READABLETEXT[109], '*')], - defaultextension='Noname.msct') - if fn is None or fn == '': - return - try: - Project_Name = fn - with open(Project_Name, 'w', encoding='utf-8') as f: - json.dump(dataset[0], f) - tkinter.messagebox.showinfo(title=READABLETEXT[4], message=READABLETEXT[107].format(Project_Name)) - is_save = True - except TypeError: - Project_Name = fn - with open(Project_Name, 'wb') as f: - pickle.dump(dataset[0], f) - tkinter.messagebox.showinfo(title=READABLETEXT[4], message=READABLETEXT[107].format(Project_Name)) - is_save = True - elif dataset[0].get('mainset').get('ReadMethod') == "class": # 等于SaveAsNewProject()函数 - fn = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[5], initialdir=r'./', - filetypes=[(READABLETEXT[108][1], '.msctn'), - (READABLETEXT[109], '*')], - defaultextension='Noname.msctn') - if fn is None or fn == '': - return - Project_Name = fn - with open(Project_Name, 'wb') as f: - pickle.dump(dataset, f) - tkinter.messagebox.showinfo(title=READABLETEXT[4], message=READABLETEXT[107].format(Project_Name)) - - is_save = True - elif dataset[0].get('mainset').get('ReadMethod') == "new": # 等于SaveAsClassProject()函数 - fn = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[5], initialdir=r'./', - filetypes=[(READABLETEXT[108][2], '.msctx'), - (READABLETEXT[109], '*')], - defaultextension='Noname.msctx') - if fn is None or fn == '': - return - Project_Name = fn - save_list = [dataset] - try: - with open("1.pkl", 'rb') as r: - save_list.append(pickle.load(r)) - except FileNotFoundError: - pass - print(save_list) - with open(Project_Name, 'wb') as f: - pickle.dump(save_list, f) - tkinter.messagebox.showinfo(title=READABLETEXT[4], message=READABLETEXT[107].format(Project_Name)) - is_save = True - - print('另存项目命令加载完成!') - - def openOldProject(): - global is_save - if is_save is not True: - result = tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[106]) - if result: - SaveProject() - fn = tkinter.filedialog.askopenfilename(title=READABLETEXT[6], initialdir=r'./', - filetypes=[(READABLETEXT[110], '.ry.nfc'), - (READABLETEXT[111], '.ry.mfm'), (READABLETEXT[112], '*')], - multiple=True) - if fn is None or fn == '': - return - else: - fn = fn[0] - from nmcsup.nmcreader import ReadOldProject - dataset[0] = ReadOldProject(fn) - - def openProject(): - global is_save - global dataset - if is_save is not True: - result = tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[106]) - if result: - SaveProject() - fn = tkinter.filedialog.askopenfilename(title=READABLETEXT[7], initialdir=r'./', - filetypes=[(READABLETEXT[108][0], '.msct'), - (READABLETEXT[108][1], '.msctn'), # msctn: 音创新文件(用类方法解析) - (READABLETEXT[108][2], '.msctx'), # msctx: 音创测试文件(用来支持多乐器解析) - (READABLETEXT[112], '*')], - multiple=True) - if fn is None or fn == '': - return - else: - fn = fn[0] - log("尝试打开:" + fn) - if str(fn)[str(fn).rfind("."):] == ".msct": # str(fn)[str(fn).rfind("."):] ->文件格式返回".xxx" - try: - try: - with open(fn, 'r', encoding='UTF-8') as C: - dataset[0] = json.load(C) - log("读取工程文件成功") - except UnicodeDecodeError: - print(READABLETEXT[8].format(fn)) - log('无法打开{}'.format(fn)) - return - except json.decoder.JSONDecodeError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,测试后改为: - # json.decoder.JSONDecodeError - print(READABLETEXT[8].format(fn)) - log('无法打开{}'.format(fn)) - return - elif str(fn)[str(fn).rfind("."):] == ".msctx": - try: - try: - with open(fn, 'rb') as C: - # print(pickle.load(C)) - read = pickle.load(C) # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # print(read) - dataset = read[0] - pkl1 = read[1] - log(f"读取新文件成功:\n{str(dataset[0])}") - with open("1.pkl", 'wb') as w: - pickle.dump(pkl1, w) - except KeyError: - with open(fn, 'rb') as C: - dataset[0] = pickle.load(C) - log(f"读取新文件成功:\n{str(dataset[0])}") - except pickle.UnpicklingError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,测试后改为: - # pickle.UnpicklingError - print(READABLETEXT[8].format(fn)) - log('无法打开{}'.format(fn)) - return - elif str(fn)[str(fn).rfind("."):] == ".msctn": - try: - try: - with open(fn, 'rb') as C: - # print(pickle.load(C)) - read = pickle.load(C) # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # print(read) - dataset = read - log("读取新文件成功") - except KeyError: - with open(fn, 'rb') as C: - dataset[0] = pickle.load(C) - log("读取新文件成功") - except pickle.UnpicklingError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,测试后改为: - # pickle.UnpicklingError - print(READABLETEXT[8].format(fn)) - log('无法打开{}'.format(fn)) - return - else: - return - global is_new_file - global ProjectName - is_new_file = False - ProjectName = fn - del fn - global NowMusic - RefreshMain() - RefreshMusic(NowMusic) - - print('打开项目命令加载完成!') - - def appabout(): - aabw = tk.Tk() - aabw.title(READABLETEXT[9]) - aabw.geometry('550x600') # 像素 - tk.Label(aabw, text='', font=('', 15)).pack() - tk.Label(aabw, text=READABLETEXT[10], font=('', 35)).pack() - tk.Label(aabw, text=READABLETEXT[11].format(VER[1] + VER[0]), font=('', 15)).pack() - # pack 的side可以赋值为LEFT RTGHT TOP BOTTOM - # grid 的row 是列数、column是行排,注意,这是针对空间控件本身大小来的,即是指向当前控件的第几个。 - # place的 x、y是(x,y)坐标 - # pic = tk.PhotoImage(file='./bin/pics/Ryoun_S.png') - # tk.Label(aabw, image=pic, width=200, height=200).pack() - # del pic - tk.Label(aabw, text='', font=('', 5)).pack() - tk.Label(aabw, text=READABLETEXT[12], font=('', 20)).pack() - tk.Label(aabw, text='', font=('', 15)).pack() - for i in READABLETEXT[15]: - tk.Label(aabw, text=i[0], font=('', 17 if i[1] else 15, 'bold' if i[1] else '')).pack() - tk.Label(aabw, text='', font=('', 5)).pack() - if DEFAULTLANGUAGE != 'zh-CN': - tk.Label(aabw, text=READABLETEXT[16], font=('', 15)).pack() - for i in READABLETEXT['Translator']: - tk.Label(aabw, text=i[0], font=('', 17 if i[1] else 15, 'bold' if i[1] else '')).pack() - - def exitAboutWindow(): - aabw.destroy() - - tk.Button(aabw, text=READABLETEXT[13], command=exitAboutWindow).pack() - - aabw.mainloop() - - print('关于命令加载完成!') - - def apphelp(): - def funcHelp(): - funTK = tk.Tk() - funTK.title("函数功能查询") - funTK.geometry('1200x1000') - thingLabel = tk.Label(funTK, text="函数功能查询", font=('', 20)) - thingLabel.pack() - aLabel = tk.Label(funTK, text="""文件:\n - 打开音·创项目...: 打开三种类型的音创文件(.msct, .msctn, .msctx)\n - 打开旧项目...: 打开两种类型的音创文件(.ry.nfc, .ry.mfm)\n - 保存项目: 自动选择保存类型,并保存为音创文件(.msct, .msctn, .msctx)\n - 另存为...: 自动选择另存为类型,并保存为音创文件(.msct, .msctn, .msctx)\n - 退出 : 退出程序\n\n - 编辑:\n - 从midi导入音轨: 以旧方法(列表方法)解析midi,如果你使用这个方法解析,意味着你选择.msct文件\n - 从midi导入音轨且用新方法解析: 以新方法(类方法)解析midi,并解析乐器信息,如果你使用这个方法解析,意味着你选择.msctx文件\n - 注意!!!这个功能暂时只用于支持雪莹乐器资源包,如果你不是为了这个,最好别用!\n - 从midi导入音轨且用类方法解析: 以类方法解析midi,如果你使用这个方法解析,意味着你选择.msctn文件\n - 注意!!!这个功能暂时在开发中!!!别用!\n - """, font=('宋体', 12)) - aLabel.pack() - - ahpw = tk.Tk() - ahpw.title(READABLETEXT[19]) - ahpw.geometry('400x600') # 像素 - tk.Label(ahpw, text="帮助", font=('楷体', 32)).grid(row=0, column=2) - tk.Button(ahpw, text="函数功能查询", command=funcHelp, font=('楷体', 20)).grid(row=1, column=1) - ahpw.mainloop() - - print('帮助命令加载完成!') - - def FromMP3(): - log('从MP3导入音乐') - mp3file = tkinter.filedialog.askopenfilename(title=READABLETEXT[20], initialdir=r'./', - filetypes=[(READABLETEXT[113], '.mp3 .m4a'), - (READABLETEXT[112], '*')], multiple=True) - if mp3file is None or mp3file == '': - log('取消') - return - else: - mp3file = mp3file[0] - from nmcsup.nmcreader import ReadMidi - from nmcsup.trans import Mp32Mid - if not os.path.exists('./Temp/'): - os.makedirs('./Temp/') - Mp32Mid(mp3file, './Temp/Trans.mid') - log('打开midi文件./Temp/Trans.mid') - th = NewThread(ReadMidi, ('./Temp/Trans.mid',)) - th.start() - del mp3file - - 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 - global NowMusic - RefreshMain() - RefreshMusic(NowMusic) - - threading.Thread(target=midiSPT, args=(th,)).start() - del th - - print('读MP3加载完成') - - def FromListMidi(): - log('从midi导入音乐') - midfile = tkinter.filedialog.askopenfilename(title=READABLETEXT[21], initialdir=r'./', - filetypes=[(READABLETEXT[114], '.mid .midi'), - (READABLETEXT[112], '*')], multiple=True) - if midfile is None or midfile == '': - log('取消') - return - else: - midfile = midfile[0] - th = NewThread(ReadMidi, (midfile,)) - th.start() - del midfile - - def midiSPT(th_): - try: - try: - for i in th_.getResult(): - datas = DMM() - datas['notes'] = i - dataset[0]['musics'].append(datas) - del th_ - global is_save - is_save = False - global NowMusic - RefreshMain() - RefreshMusic(NowMusic) - except OSError: - tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) - except AttributeError: - try: - tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) - except OSError: - tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) - - threading.Thread(target=midiSPT, args=(th,)).start() - del th - - def FromNewMidi(): - log('从midi导入音乐并采用新读取方式') - midfile = tkinter.filedialog.askopenfilename(title=READABLETEXT[21], initialdir=r'./', - filetypes=[(READABLETEXT[114], '.mid .midi'), - (READABLETEXT[112], '*')], multiple=True) - if midfile is None or midfile == '': - log('取消') - return - else: - midfile = midfile[0] - th = NewThread(LoadMidi, (midfile,)) - th.start() - del midfile - - def midiSPT(th_): - try: - try: - for i in th_.getResult(): - datas = DMM() - datas['notes'] = i - dataset[0]['musics'].append(datas) - del th_ - global is_save - is_save = False - global NowMusic - RefreshMain() - RefreshMusic(NowMusic) - except OSError: - tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) - except AttributeError: - try: - tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) - except OSError: - tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) - - threading.Thread(target=midiSPT, args=(th,)).start() - del th - dataset[0]['mainset']['ReadMethod'] = "new" - - def FromClassMidi(): - log('从midi导入音乐并采用类读取方式') - midfile = tkinter.filedialog.askopenfilename(title=READABLETEXT[21], initialdir=r'./', - filetypes=[(READABLETEXT[114], '.mid .midi'), - (READABLETEXT[112], '*')], multiple=True) - if midfile is None or midfile == '': - log('取消') - return - else: - midfile = midfile[0] - th = NewThread(MidiAnalysisClass, (midfile,)) - th.start() - del midfile - - 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 - global NowMusic - RefreshMain() - RefreshMusic(NowMusic) - threading.Thread(target=midiSPT, args=(th,)).start() - del th - dataset[0]['mainset']['ReadMethod'] = "class" - - print('读midi命令加载完成!') - - def FromForm(): - log('从文本读入音轨') - fn = tkinter.filedialog.askopenfilename(title=READABLETEXT[22], initialdir=r'./', - filetypes=[(READABLETEXT[115], '.txt'), (READABLETEXT[112], '*')], - multiple=True) - if fn is None or fn == '': - log('取消') - return - else: - fn = fn[0] - th = NewThread(ReadFile, (fn,)) - 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 - global NowMusic - RefreshMain() - RefreshMusic(NowMusic) - - threading.Thread(target=midiSPT, args=(th,)).start() - - print('读txt命令加载完成!') - - def FromText(): - log('写入音符至音轨') - dat = tkinter.simpledialog.askstring(title=READABLETEXT[23], prompt=READABLETEXT[14], initialvalue='`1 .2 C') - if dat is None: - return - datas = [] - for i in dat.split(' '): - datas.append([str(i), 1.0]) - log(READABLETEXT[24].format(str(datas))) - from nmcsup.trans import note2list - datat = DMM() - datat['notes'] = note2list(datas) - dataset[0]['musics'].append(datat) - del datas, datat, dat - global is_save - is_save = False - global NowMusic - RefreshMain() - RefreshMusic(NowMusic) - - print('写入命令加载完成!') - print('开始加载列表生成函数函数。') - - def ShowCMD(): - log('展示指令') - global NowMusic - from nmcsup.trans import Note2Cmd - RefreshCMDList( - Note2Cmd(dataset[0]['musics'][NowMusic]['notes'], dataset[0]['musics'][NowMusic]['set']['ScoreboardName'], - dataset[0]['musics'][NowMusic]['set']['Instrument'], dataset[0]['mainset']['PlayerSelect'])) - - def MakeCMD(): - log('生成文件') - from msctspt.funcOpera import makeFuncFiles - file = tkinter.filedialog.askdirectory(title=READABLETEXT[25], initialdir=r'./') - if file is None or file == '': - log('取消') - return - else: - makeFuncFiles(dataset[0], file + '/') - - def MakeCMDdir(): - log('生成函数包') - from msctspt.funcOpera import makeFunDir - file = tkinter.filedialog.askdirectory(title=READABLETEXT[26], initialdir=r'./') - if file is None or file == '': - log('取消') - return - else: - makeFunDir(dataset[0], file + '/') - - def MakePackFile(): - file = tkinter.filedialog.askdirectory(title=READABLETEXT[27], initialdir=r'./') - if file is None or file == '': - log('取消') - return - import zipfile - - from msctspt.funcOpera import makeFunDir - log('生成附加包文件') - if not os.path.exists('./temp/'): - os.makedirs('./temp/') - makeFunDir(dataset[0], './temp/') - - shutil.move('./temp/{}Pack/behavior_packs/{}/functions'.format(dataset[0]['mainset']['PackName'], - dataset[0]['mainset']['PackName']), './') - - shutil.move('./temp/{}Pack/behavior_packs/{}/manifest.json'.format(dataset[0]['mainset']['PackName'], - dataset[0]['mainset']['PackName']), './') - - with zipfile.ZipFile('{}/{}.mcpack'.format(file, dataset[0]['mainset']['PackName']), 'w') as zipobj: - for i in os.listdir('./functions/'): - zipobj.write('./functions/{}'.format(i)) - zipobj.write('./manifest.json') - shutil.move('./functions', './temp/') - shutil.move('./manifest.json', './temp/') - shutil.rmtree('./temp/') - - print('完成加载列表生成函数函数。') - print('开始加载乐器类生成函数函数。') - - def MakeNewCMD(): - log('生成新文件') - from msctspt.funcOpera import makeNewFuncFiles - file = tkinter.filedialog.askdirectory(title=READABLETEXT[25], initialdir=r'./') - if file is None or file == '': - log('取消') - return - else: - makeNewFuncFiles(dataset[0], file + '/') - - def MakeNewCMDdir(): - log('生成新函数包与材质包') - from msctspt.funcOpera import makeNewFunDir - file = tkinter.filedialog.askdirectory(title=READABLETEXT[26], initialdir=r'./') - if file is None or file == '': - log('取消') - return - else: - makeNewFunDir(dataset[0], file + '/') - - def MakeNewFunctionPackFile(): - file = tkinter.filedialog.askdirectory(title=READABLETEXT[27], initialdir=r'./') - if file is None or file == '': - log('取消') - return - import zipfile - - from msctspt.funcOpera import makeNewFunDir - log('生成附加包文件') - if not os.path.exists('./temp/'): - os.makedirs('./temp/') - makeNewFunDir(dataset[0], './temp/') - - shutil.move('./temp/{}Pack/behavior_packs/{}/functions'.format(dataset[0]['mainset']['PackName'], - dataset[0]['mainset']['PackName']), './') - - shutil.move('./temp/{}Pack/behavior_packs/{}/manifest.json'.format(dataset[0]['mainset']['PackName'], - dataset[0]['mainset']['PackName']), './') - - with zipfile.ZipFile('{}/{}.mcpack'.format(file, dataset[0]['mainset']['PackName']), 'w') as zipobj: - for i in os.listdir('./functions/'): - zipobj.write('./functions/{}'.format(i)) - zipobj.write('./manifest.json') - shutil.move('./functions', './temp/') - shutil.move('./manifest.json', './temp/') - shutil.rmtree('./temp/') - - def MakeNewFunctionPack_ResourcesPacks_File(): # 这个是直接复制资源包(散包) - file = tkinter.filedialog.askdirectory(title=READABLETEXT[27], initialdir=r'./') - if file is None or file == '': - log('取消') - return - from bgArrayLib.sy_resourcesPacker import resources_pathSetting - result = resources_pathSetting() - print(result) - if result[0] is False: - if result[1] == 1: - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[157]) - if result[1] == 2: - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[158]) - return - else: - import zipfile - - from msctspt.funcOpera import makeNewFunDir - log('生成附加包文件') - if not os.path.exists('./temp/'): - os.makedirs('./temp/') - makeNewFunDir(dataset[0], './temp/') - - shutil.move('./temp/{}Pack/behavior_packs/{}/functions'.format(dataset[0]['mainset']['PackName'], - dataset[0]['mainset']['PackName']), './') - - shutil.move('./temp/{}Pack/behavior_packs/{}/manifest.json'.format(dataset[0]['mainset']['PackName'], - dataset[0]['mainset']['PackName']), './') - - with zipfile.ZipFile('{}/{}.mcpack'.format(file, dataset[0]['mainset']['PackName']), 'w') as zipobj: - for i in os.listdir('./functions/'): - zipobj.write('./functions/{}'.format(i)) - zipobj.write('./manifest.json') - shutil.move('./functions', './temp/') - shutil.move('./manifest.json', './temp/') - shutil.rmtree('./temp/') - from bgArrayLib.sy_resourcesPacker import scatteredPack - scatteredPack(file) - - print('完成加载乐器类生成函数函数。') - print('开始加载乐器音色资源绑定函数。') - - def changeResourcesPath(): - file = tkinter.filedialog.askdirectory(title=READABLETEXT[27], initialdir=r'./') - if file is None or file == '': - log('取消') - return - from bgArrayLib.sy_resourcesPacker import resources_pathSetting - result = resources_pathSetting(file) - print(result) - if result[0] is False: - if result[1] == 1: - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[157]) - if result[1] == 2: - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[158]) - else: - tkinter.messagebox.showinfo(title=READABLETEXT[1], message=READABLETEXT[159]) - - print('开始加载类生成函数函数。') - - def MakeClassCMD(): - log('生成类文件') - from msctspt.funcOpera import makeClassFuncFiles - file = tkinter.filedialog.askdirectory(title=READABLETEXT[25], initialdir=r'./') - if file is None or file == '': - log('取消') - return - else: - makeClassFuncFiles(dataset[0], file + '/') - - def MakeClassCMDdir(): - log('生成类函数包与材质包') - from msctspt.funcOpera import makeClassFunDir - file = tkinter.filedialog.askdirectory(title=READABLETEXT[26], initialdir=r'./') - if file is None or file == '': - log('取消') - return - else: - makeClassFunDir(dataset[0], file + '/') - - def MakeClassFunctionPackFile(): - file = tkinter.filedialog.askdirectory(title=READABLETEXT[27], initialdir=r'./') - if file is None or file == '': - log('取消') - return - import zipfile - - from msctspt.funcOpera import makeClassFunDir - log('生成附加包文件') - if not os.path.exists('./temp/'): - os.makedirs('./temp/') - makeClassFunDir(dataset[0], './temp/') - - shutil.move('./temp/{}Pack/behavior_packs/{}/functions'.format(dataset[0]['mainset']['PackName'], - dataset[0]['mainset']['PackName']), './') - - shutil.move('./temp/{}Pack/behavior_packs/{}/manifest.json'.format(dataset[0]['mainset']['PackName'], - dataset[0]['mainset']['PackName']), './') - - with zipfile.ZipFile('{}/{}.mcpack'.format(file, dataset[0]['mainset']['PackName']), 'w') as zipobj: - for i in os.listdir('./functions/'): - zipobj.write('./functions/{}'.format(i)) - zipobj.write('./manifest.json') - shutil.move('./functions', './temp/') - shutil.move('./manifest.json', './temp/') - shutil.rmtree('./temp/') - - print('完成加载类生成函数函数。') - print('开始加载地图函数。') - - # 转为空方块世界 - def ToBlockWorldEpt(): - import zipfile - global dire - - from nmcsup.trans import Cmd2World, Datas2BlkWorld, Notes2Player - while True: - try: - dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], - initialvalue='16 4 16') - if dire is None or dire == '': - return - dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') - if Outdire is None or Outdire == '': - log('取消') - return - else: - Outdire = '{}/{}/'.format(Outdire[0], dataset[0]['mainset']['PackName']) - with zipfile.ZipFile('./nmcsup/EptWorld.zip') as zipobj: # , 'r' (参数等于默认时不写) - zipobj.extractall(Outdire) - NoteData = [] - for i in dataset[0]['musics']: - NoteData.append(i['notes']) - Datas2BlkWorld(NoteData, Outdire, dire) - del NoteData - for i in range(len(dataset[0]['musics'])): - Cmd2World(Notes2Player(dataset[0]['musics'][i]['notes'], [dire[0], dire[1], dire[2] + i], - {'Ent': dataset[0]['musics'][i]['set']['EntityName'], - 'Pls': dataset[0]['mainset']['PlayerSelect'], - 'Ins': dataset[0]['musics'][i]['set']['Instrument']}), Outdire, - [dire[0] - 5 - i, dire[1], dire[2]]) - del dire, Outdire - - # 转为已存在的方块世界 - def ToBlockWorld(): - from nmcsup.trans import Cmd2World, Datas2BlkWorld, Notes2Player - global dire - while True: - try: - dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], - initialvalue='16 4 16') - if dire is None or dire == '': - return - dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') - if Outdire is None or Outdire == '': - log('取消') - return - else: - Outdire += '/' - NoteData = [] - for i in dataset[0]['musics']: - NoteData.append(i['notes']) - Datas2BlkWorld(NoteData, Outdire, dire) - del NoteData - for i in range(len(dataset[0]['musics'])): - Cmd2World(Notes2Player(dataset[0]['musics'][i]['notes'], [dire[0], dire[1], dire[2] + i], - {'Ent': dataset[0]['musics'][i]['set']['EntityName'], - 'Pls': dataset[0]['mainset']['PlayerSelect'], - 'Ins': dataset[0]['musics'][i]['set']['Instrument']}), Outdire, - [dire[0] - 5 - i, dire[1], dire[2]]) - del dire, Outdire - - # 生成函数播放器 - def MakeFuncPlayer(): - global dire - while True: - try: - dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], - initialvalue='16 4 16') - if dire is None or dire == '': - return - dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[30], initialdir=r'./') - if Outdire is None or Outdire == '': - return - else: - Outdire = '{}/{}/'.format(Outdire, dataset[0]['mainset']['PackName']) - from nmcsup.trans import Notes2Player - for i in range(len(dataset[0]['musics'])): - open(Outdire + dataset[0]['musics'][i]['set']['FileName'] + '_' + str(i) + '.mcfunction', 'w', - encoding='utf-8').writelines( - Notes2Player(dataset[0]['musics'][i]['notes'], [dire[0], dire[1], dire[2] + i], - {'Ent': dataset[0]['musics'][i]['set']['EntityName'], - 'Pls': dataset[0]['mainset']['PlayerSelect'], - 'Ins': dataset[0]['musics'][i]['set']['Instrument']})) - - # 转为空指令世界 - def ToCmdWorldEpt(): - import zipfile - global dire - - from nmcsup.trans import Cmd2World, Note2Cmd - while True: - try: - dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], - initialvalue='16 4 16') - if dire is None or dire == '': - return - dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') - if Outdire is None or Outdire == '': - return - else: - Outdire += '/' + dataset[0]['mainset']['PackName'] + '/' - with zipfile.ZipFile('./nmcsup/EptWorld.zip') as zipobj: # , 'r' (默认参数不用设置) - zipobj.extractall(Outdire) - for i in range(len(dataset[0]['musics'])): - Cmd2World(Note2Cmd(dataset[0]['musics'][i]['notes'], dataset[0]['musics'][i]['set']['ScoreboardName'], - dataset[0]['musics'][i]['set']['Instrument'], dataset[0]['mainset']['PlayerSelect'], - True), Outdire, [dire[0], dire[1], dire[2] + i]) - del dire, Outdire - - # 转为已存在的指令世界 - def ToCmdWorld(): - global dire - from nmcsup.trans import Cmd2World, Note2Cmd - while True: - try: - dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], - initialvalue='16 4 16') - if dire is None or dire == '': - return - dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') - if Outdire is None or Outdire == '': - return - else: - Outdire += '/' - for i in range(len(dataset[0]['musics'])): - Cmd2World(Note2Cmd(dataset[0]['musics'][i]['notes'], dataset[0]['musics'][i]['set']['ScoreboardName'], - dataset[0]['musics'][i]['set']['Instrument'], dataset[0]['mainset']['PlayerSelect'], - True), Outdire, [dire[0], dire[1], dire[2] + i]) - del dire, Outdire - - # 函数输入指令块 - def func2World(): - from nmcsup.trans import Cmd2World - global dire - while True: - try: - dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], - initialvalue='16 4 16') - if dire is None or dire == '': - return - dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') - if Outdire is None or Outdire == '': - return - else: - Outdire += '/' - Cmd2World(open(tkinter.filedialog.askopenfilename(title=READABLETEXT[31], initialdir=r'./', - filetypes=[(READABLETEXT[118], '.mcfunction'), - (READABLETEXT[112], '*')], multiple=True)[0], 'r', - encoding='utf-8').readlines(), Outdire, dire) - - # 大函数分割并载入执行链 - def bigFunc2World(): - log('分割大函数') - global dire - import uuid - - from msctspt.funcOpera import funSplit - from msctspt.transfer import hans2pinyin - from nmcsup.trans import Cmd2World - while True: - try: - dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[119], - initialvalue='16 4 16') - if dire is None or dire == '': - return - dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') - if Outdire is None or Outdire == '': - log('取消') - return - else: - Outdire += '/' - log('获得地图地址:' + Outdire) - fileName = tkinter.filedialog.askopenfilename(title=READABLETEXT[31], initialdir=r'./', - filetypes=[(READABLETEXT[118], '.mcfunction'), - (READABLETEXT[112], '*')], multiple=True) - if fileName is None or fileName == '': - log('取消') - return - else: - fileName = fileName[0] - log('获得文件名:' + fileName) - bigFile = open(fileName, 'r', encoding='utf-8') - parts = funSplit(bigFile) - if parts == -1: - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[121]) - return - log('创建函数文件夹') - packName = fileName[len(fileName) - fileName[::-1].index('/'):fileName.index('.')] - packDire = hans2pinyin(packName) - try: - os.makedirs(Outdire + 'behavior_packs/' + packDire + '/functions/') - except FileExistsError: - log('已存在文件夹') - log('创建manifest.json以及world_behavior_packs.json') - behaviorUuid = uuid.uuid4() - if os.path.exists(Outdire + 'world_behavior_packs.json'): - with open(Outdire + 'world_behavior_packs.json', 'r') as f: - have = json.load(f) - have.append({'pack_id': str(behaviorUuid), 'version': [0, 0, 1]}) - with open(Outdire + 'world_behavior_packs.json', 'w', encoding='utf-8') as f: - json.dump(have, f) - del have - else: - with open(Outdire + 'world_behavior_packs.json', 'w', encoding='utf-8') as f: - f.write('[\n {\'pack_id\': \'' + str(behaviorUuid) + '\',\n \'version\': [ 0, 0, 1 ]}\n]') - with open(Outdire + 'behavior_packs/' + packDire + '/manifest.json', 'w') as f: - f.write( - '{\n \'format_version\': 1,\n \'header\': {\n \'description\': \'' + packName + - ' Pack : behavior pack\',\n \'version\': [ 0, 0, 1 ],\n \'name\': \'' + packName + - 'Pack\',\n \'uuid\': \'' + str( - behaviorUuid) + '\'\n },\n \'modules\': [\n {\n \'description\': \'' + packName + - ' Pack : behavior pack\',\n \'type\': ' - '\'data\',\n \'version\': [ 0, 0, 1 ],\n \'uuid\': \'' + str( - uuid.uuid4()) + '\'\n }\n ]\n}') # 要求文段不能过长 - cmdlist = [] - for i in parts: - open(Outdire + 'behavior_packs/' + packDire + '/functions/' + packDire + str( - parts.index(i) + 1) + '.mcfunction', 'w', encoding='utf-8').writelines(i) - cmdlist.append('function ' + packDire + str(parts.index(i) + 1)) - Cmd2World(cmdlist, Outdire, dire) - del cmdlist, behaviorUuid, Outdire, fileName, bigFile, parts, dire, packName, packDire - - def toScbBDXfile(): - log('单音轨转BDX') - from msctspt.transfer import note2bdx - global dire - while True: - try: - dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[122], - initialvalue='0 0 0') - if dire is None or dire == '': - return - dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - - fileName = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[32], initialdir=r'./', - filetypes=[(READABLETEXT[123], '.bdx'), - (READABLETEXT[112], '*')], - defaultextension=dataset[0]['mainset']['PackName'] + '.bdx', - initialfile=dataset[0]['mainset']['PackName'] + '.bdx') - if fileName is None or fileName == '': - log('取消') - return - - log('获得文件名:' + fileName) - - res = note2bdx(fileName, dire, dataset[0]['musics'][NowMusic]['notes'], - dataset[0]['musics'][NowMusic]['set']['ScoreboardName'], - dataset[0]['musics'][NowMusic]['set']['Instrument'], dataset[0]['mainset']['PlayerSelect']) - log('转换结束!\n' + str(res)) - tkinter.messagebox.showinfo(READABLETEXT[33], READABLETEXT[124].format(str(res))) - - def toBDXfile(): - log('整首歌转BDX') - from msctspt.transfer import music2BDX - global dire - while True: - try: - dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[122], - initialvalue='0 0 0') - if dire is None or dire == '': - return - dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - - fileName = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[32], initialdir=r'./', - filetypes=[(READABLETEXT[123], '.bdx'), - (READABLETEXT[112], '*')], - defaultextension=dataset[0]['mainset']['PackName'] + '.bdx', - initialfile=dataset[0]['mainset']['PackName'] + '.bdx') - - maxHeight = 200 - print(maxHeight) # 使用变量 - - while True: - maxHeight = tkinter.simpledialog.askinteger(title=READABLETEXT[28], - prompt=READABLETEXT[93], - initialvalue='200') - if maxHeight >= 5: - break - elif maxHeight is None: - log('取消') - return - else: - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[94]) - continue - - if fileName is None or fileName == '': - log('取消') - return - - log('获得文件名:' + fileName) - - res = music2BDX(fileName, dire, dataset[0], ) - log('转换结束!\n' + str(res)) - tkinter.messagebox.showinfo(READABLETEXT[33], READABLETEXT[124].format(str(res))) - - def wsPlay(): - from msctspt.transfer import note2webs - spd = tkinter.simpledialog.askfloat(READABLETEXT[34], prompt=READABLETEXT[125], initialvalue='5.0') - tkinter.messagebox.showinfo(title=READABLETEXT[35], message=READABLETEXT[126]) - note2webs(dataset[0]['musics'][NowMusic]['notes'], dataset[0]['musics'][NowMusic]['set']['Instrument'], spd, - dataset[0]['mainset']['PlayerSelect']) - - def toRSworldEPT(): - import zipfile - global dire - dire = "" - - from msctspt.transfer import note2RSworld - while True: - try: - dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], - initialvalue='16 4 16') - if dire is None or dire == '': - return - dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') - if Outdire is None or Outdire == '': - return - else: - Outdire += '/' + dataset[0]['mainset']['PackName'] + '/' - with zipfile.ZipFile('./nmcsup/EptWorld.zip') as zipobj: # , 'r'(默认参数不用写) - zipobj.extractall(Outdire) - for i in range(len(dataset[0]['musics'])): - note2RSworld(Outdire, dire, dataset[0]['musics'][i]['notes'], dataset[0]['musics'][i]['set']['Instrument']) - - del dire, Outdire - - def toRSworld(): - from msctspt.transfer import note2RSworld - global dire - dire = "" - while True: - try: - dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], - initialvalue='16 4 16') - if dire is None or dire == '': - return - dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') - if Outdire is None or Outdire == '': - return - else: - Outdire += '/' - for i in range(len(dataset[0]['musics'])): - note2RSworld(Outdire, dire, dataset[0]['musics'][i]['notes'], dataset[0]['musics'][i]['set']['Instrument']) - del dire, Outdire - - def world2RyStruct(): - global begp - global endp - outdir = tkinter.filedialog.askdirectory(title=READABLETEXT[36], initialdir=r'./') - if outdir is None or outdir == '': - return - else: - outdir += '/' - while True: - try: - begp = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[127], - initialvalue='16 4 16') - if begp is None or begp == '': - return - begp = [int(begp.split(' ')[0]), int(begp.split(' ')[1]), int(begp.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - while True: - try: - endp = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[128], - initialvalue='16 4 16') - if endp is None or endp == '': - return - endp = [int(endp.split(' ')[0]), int(endp.split(' ')[1]), int(endp.split(' ')[2])] - except ValueError: # 测试完为ValueError,故修改语法 - tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) - continue - break - isAir = tkinter.messagebox.askyesno(READABLETEXT[37], READABLETEXT[129]) - fileName = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[38], initialdir=r'./', - filetypes=[(READABLETEXT[130], '.RyStruct'), - (READABLETEXT[112], '*')], - defaultextension='*.RyStruct', initialfile='*.RyStruct') - if fileName is None or fileName == '': - log('取消') - return - from msctspt.transfer import ryStruct - rys = ryStruct(outdir) - rys.world2Rys(begp, endp, isAir) - # error1 = True - try: - with open(fileName, 'w', encoding='utf-8') as f: - json.dump(rys.RyStruct, f, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False) - tkinter.messagebox.showinfo(READABLETEXT[33], READABLETEXT[131].format(fileName)) - # error1 = False - except: - tkinter.messagebox.showerror(READABLETEXT[39], READABLETEXT[132].format(fileName, str(rys.RyStruct))) - rys.closeLevel() - # finally: - # if error1 is True: - # tkinter.messagebox.showerror(READABLETEXT[39], READABLETEXT[132].format(fileName, str(rys.RyStruct))) - # rys.closeLevel() - - def world2BDX(): - tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[133]) - - # 使用邮件反馈bug - def sendBugReport(): - from msctspt.bugReporter import report - name = tkinter.simpledialog.askstring(title=READABLETEXT[40], prompt=READABLETEXT[134]) - contact = tkinter.simpledialog.askstring(title=READABLETEXT[40], prompt=READABLETEXT[135]) - describetion = tkinter.simpledialog.askstring(title=READABLETEXT[40], prompt=READABLETEXT[136]) - report(name, contact, describetion).emailReport() - del name, contact, describetion - - def ClearLog(): - global clearLog - clearLog = not clearLog - if clearLog: - tkinter.messagebox.showinfo(READABLETEXT[33], READABLETEXT[137]) - else: - tkinter.messagebox.showinfo(READABLETEXT[33], READABLETEXT[138]) - - print('生成部分及其余命令加载完成!') - - print('完成!') - - # 窗口部分 - print('增加窗口元素...') - global root - global __version__ - - root.title(READABLETEXT[41].format(__version__)) - root.geometry('900x900') # 像素 - root.iconbitmap('./resources/musicreater.ico', './resources/musicreater.ico') - - print('完成!') - - print('加载点击与页面更新命令...') - - # 音轨菜单被点击 - - def MusicList_selected(event): - global NowMusic - NowMusic = ListMusicList.get(ListMusicList.curselection()) - log('刷新音轨' + str(NowMusic)) - RefreshMusic(NowMusic) - print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) - - # 音符菜单被点击 - def NoteList_selected(event): - print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) - pass # 编辑音符操作 - - def CMDList_selected(event): - print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) - pass # 命令编辑操作 - - CMDList_selected("") # 保证函数使用 - # !!!!!上面这行在写完这个函数之后记得删!!!! - - print('菜单点击命令加载完成!') - - # 刷新音轨部分 - def RefreshMusic(Music=0): - LabelEntityName['text'] = READABLETEXT[42].format(dataset[0]['musics'][Music]['set']['EntityName']) - LabelScoreboardName['text'] = READABLETEXT[43].format(dataset[0]['musics'][Music]['set']['ScoreboardName']) - LabelInstrument['text'] = READABLETEXT[44].format(dataset[0]['musics'][Music]['set']['Instrument']) - LabelFileName['text'] = READABLETEXT[45].format(dataset[0]['musics'][Music]['set']['FileName']) - NoteList_var.set(()) # 为列表框设置新值 - for i in dataset[0]['musics'][Music]['notes']: - ListNoteList.insert(tk.END, str(i)) - - # 刷新主要部分 - def RefreshMain(): - LabelPackName['text'] = READABLETEXT[46].format(str(dataset[0]['mainset']['PackName'])) - # print(LabelPackName) - LabelMusicTitle['text'] = READABLETEXT[47].format(str(dataset[0]['mainset']['MusicTitle'])) - LabelIsRepeat['text'] = READABLETEXT[48].format(str(dataset[0]['mainset']['IsRepeat'])) - LabelPlayerSelect['text'] = READABLETEXT[49].format(str(dataset[0]['mainset']['PlayerSelect'])) - MusicList_var.set(()) # 为列表框设置新值 - for i in range(len(dataset[0]['musics'])): - ListMusicList.insert(tk.END, i) - global NowMusic - NowMusic = 0 - - def RefreshCMDList(CMDList): - ListCMDList.delete(tk.END) - for i in CMDList: - ListCMDList.insert(tk.END, str(i)) - - print('页面刷新函数加载完成!') - - def changePackName(event): - a = tkinter.simpledialog.askstring(title=READABLETEXT[50], prompt=READABLETEXT[139], initialvalue='Ryoun') - if a is None: - return - dataset[0]['mainset']['PackName'] = a - del a - RefreshMain() - print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) - - def changeMusicTitle(event): - a = tkinter.simpledialog.askstring(title=READABLETEXT[50], prompt=READABLETEXT[140], initialvalue='Noname') - if a is None: - return - dataset[0]['mainset']['MusicTitle'] = a - RefreshMain() - print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) - - def changeIsRepeat(event): - dataset[0]['mainset']['IsRepeat'] = not dataset[0]['mainset']['IsRepeat'] - RefreshMain() - print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) - - def changePlayerSelect(event): - dataset[0]['mainset']['PlayerSelect'] = tkinter.simpledialog.askstring(title=READABLETEXT[50], - prompt=READABLETEXT[141], - initialvalue='') - if dataset[0]['mainset']['PlayerSelect'] is None: - dataset[0]['mainset']['PlayerSelect'] = '' - RefreshMain() - print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) - - def changeEntityName(event): - global NowMusic - a = tkinter.simpledialog.askstring(title=READABLETEXT[51], prompt=READABLETEXT[142], - initialvalue='musicSupport') - if a is None: - return - dataset[0]['musics'][NowMusic]['set']['EntityName'] = a - RefreshMusic(NowMusic) - print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) - - def changeScoreboardName(event): - global NowMusic - a = tkinter.simpledialog.askstring(title=READABLETEXT[51], prompt=READABLETEXT[143], - initialvalue='musicSupport') - if a is None: - return - dataset[0]['musics'][NowMusic]['set']['ScoreboardName'] = a - RefreshMusic(NowMusic) - print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) - - def changeInstrument(event): - from nmcsup.const import Instuments as inst - global NowMusic - while True: # 改正:(True) - instemp = tkinter.simpledialog.askstring(title=READABLETEXT[51], prompt=READABLETEXT[144], - initialvalue='note.harp') - if instemp not in inst.keys(): # 改正:not instemp in inst.keys() ,not in 为固定写法 - if tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[145]): - dataset[0]['musics'][NowMusic]['set']['Instrument'] = instemp - del instemp - break - else: - smsg = READABLETEXT[52] - for i, j in inst.items(): - smsg += i + ' : ' + j + '\n' - tkinter.messagebox.showinfo(title=READABLETEXT[1], message=smsg) - del smsg - else: - dataset[0]['musics'][NowMusic]['set']['Instrument'] = instemp - del instemp - break - RefreshMusic(NowMusic) - print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) - - def changeFileName(event): - global NowMusic - a = tkinter.simpledialog.askstring(title=READABLETEXT[51], prompt=READABLETEXT[146], initialvalue='Music') - if a is None: - return - dataset[0]['musics'][NowMusic]['set']['FileName'] = a - RefreshMusic(NowMusic) - print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) - - print('标签点击命令加载完成!') - - def ResetSetting(): - global dataset - dataset[0]['mainset'] = {'PackName': 'Ryoun', 'MusicTitle': 'Noname', 'IsRepeat': False, 'PlayerSelect': ''} - RefreshMain() - - def DelNowMusic(): - global NowMusic - del dataset[0]['musics'][NowMusic] - NowMusic -= 1 - RefreshMain() - RefreshMusic(NowMusic) - - from nmcsup.vers import resetver - - print('按钮点击命令加载完成!') - print('完成!') - print('加载菜单与页面...') - - # 创建一个菜单 - main_menu_bar = tk.Menu(root) - - # 创建文件菜单 - filemenu = tk.Menu(main_menu_bar, tearoff=0) - - filemenu.add_command(label=READABLETEXT[53], command=openProject) - filemenu.add_command(label=READABLETEXT[54], command=openOldProject) - filemenu.add_command(label=READABLETEXT[55], command=SaveProject) - filemenu.add_command(label=READABLETEXT[56], command=SaveAsProject) - - filemenu.add_separator() # 分隔符 - - filemenu.add_command(label=READABLETEXT[57], command=exitapp) - - # 将子菜单加入到菜单条中 - main_menu_bar.add_cascade(label=READABLETEXT[58], menu=filemenu) - - # 创建编辑菜单 - editmenu = tk.Menu(main_menu_bar, tearoff=0) - editmenu.add_command(label=READABLETEXT[59], command=FromMP3) - editmenu.add_command(label=READABLETEXT[60], command=FromListMidi) - editmenu.add_command(label=READABLETEXT[61], command=FromForm) - editmenu.add_command(label=READABLETEXT[62], command=FromText) - editmenu.add_separator() - editmenu.add_command(label=READABLETEXT[160], command=FromClassMidi) - editmenu.add_command(label=READABLETEXT[148], command=FromNewMidi) - # 将子菜单加入到菜单条中 - main_menu_bar.add_cascade(label=READABLETEXT[63], menu=editmenu) - - # 创建函数菜单 - funcmenu = tk.Menu(main_menu_bar, tearoff=0) - funcmenu.add_command(label=READABLETEXT[64], command=MakeCMD) - funcmenu.add_command(label=READABLETEXT[65], command=MakeCMDdir) - funcmenu.add_command(label=READABLETEXT[66], command=MakePackFile) - funcmenu.add_separator() - funcmenu.add_command(label=READABLETEXT[147], command=MakeNewCMD) - funcmenu.add_command(label=READABLETEXT[153], command=MakeNewCMDdir) - funcmenu.add_command(label=READABLETEXT[154], command=MakeNewFunctionPackFile) - funcmenu.add_command(label=READABLETEXT[155], command=MakeNewFunctionPack_ResourcesPacks_File) - funcmenu.add_separator() - funcmenu.add_command(label=READABLETEXT[164], command=MakeClassCMD) - funcmenu.add_command(label=READABLETEXT[165], command=MakeClassCMDdir) - funcmenu.add_command(label=READABLETEXT[166], command=MakeClassFunctionPackFile) - - # 将子菜单加入到菜单条中 - main_menu_bar.add_cascade(label=READABLETEXT[67], menu=funcmenu) - - # 创建世界菜单 - worldmenu = tk.Menu(main_menu_bar, tearoff=0) - worldmenu.add_command(label=READABLETEXT[68], command=ToBlockWorldEpt) - worldmenu.add_command(label=READABLETEXT[69], command=ToBlockWorld) - worldmenu.add_separator() - worldmenu.add_command(label=READABLETEXT[70], command=ToCmdWorldEpt) - worldmenu.add_command(label=READABLETEXT[71], command=ToCmdWorld) - worldmenu.add_separator() - worldmenu.add_command(label=READABLETEXT[72], command=toRSworldEPT) - worldmenu.add_command(label=READABLETEXT[73], command=toRSworld) - # 将子菜单加入到菜单条中 - main_menu_bar.add_cascade(label=READABLETEXT[74], menu=worldmenu) - - # 创建结构功能菜单 - structureMenu = tk.Menu(main_menu_bar, tearoff=0) - structureMenu.add_command(label=READABLETEXT[92], command=toBDXfile) - structureMenu.add_command(label=READABLETEXT[76], command=toScbBDXfile) - structureMenu.add_command(label=READABLETEXT[77], command=world2BDX) - structureMenu.add_separator() - structureMenu.add_command(label=READABLETEXT[78], command=world2RyStruct) - - main_menu_bar.add_cascade(label=READABLETEXT[95], menu=structureMenu) - - # 创建辅助功能菜单 - otherMenu = tk.Menu(main_menu_bar, tearoff=0) - otherMenu.add_command(label=READABLETEXT[75], command=MakeFuncPlayer) - otherMenu.add_separator() - otherMenu.add_command(label=READABLETEXT[79], command=func2World) - otherMenu.add_command(label=READABLETEXT[80], command=bigFunc2World) - - main_menu_bar.add_cascade(label=READABLETEXT[81], menu=otherMenu) - - # 创建实验功能菜单 - trymenu = tk.Menu(main_menu_bar, tearoff=0) - trymenu.add_command(label=READABLETEXT[82], command=ShowCMD) - trymenu.add_command(label=READABLETEXT[83], command=wsPlay) - # 将子菜单加入到菜单条中 - main_menu_bar.add_cascade(label=READABLETEXT[84], menu=trymenu) - - # 创建帮助菜单 - helpmenu = tk.Menu(main_menu_bar, tearoff=0) - helpmenu.add_command(label=READABLETEXT[85], command=ClearLog) - helpmenu.add_command(label=READABLETEXT[86], command=resetver) - helpmenu.add_command(label=READABLETEXT[152], command=end) - helpmenu.add_command(label=READABLETEXT[156], command=changeResourcesPath) - - helpmenu.add_separator() # 分隔符 - - helpmenu.add_command(label=READABLETEXT[87], command=apphelp) - helpmenu.add_command(label=READABLETEXT[88], command=appabout) - helpmenu.add_command(label=READABLETEXT[89], command=sendBugReport) - # 将子菜单加入到菜单条中 - main_menu_bar.add_cascade(label=READABLETEXT[90], menu=helpmenu) - - # 窗口内容 - - # 上半部分框 - UpFrame = tk.Frame(root) - - # 左边的框(音乐总设置) - UpLeftFrame = tk.Frame(UpFrame, bg='white') - # 大标题 - tk.Label(UpLeftFrame, text=READABLETEXT[91], font=('', 20)).pack() - # 按钮式文本 - LabelPackName = tk.Label(UpLeftFrame, bg='white', - text=READABLETEXT[46].format(str(dataset[0]['mainset']['PackName'])), font=('', 15)) - LabelMusicTitle = tk.Label(UpLeftFrame, bg='white', - text=READABLETEXT[47].format(str(dataset[0]['mainset']['MusicTitle'])), font=('', 15)) - LabelIsRepeat = tk.Label(UpLeftFrame, bg='white', - text=READABLETEXT[48].format(str(dataset[0]['mainset']['IsRepeat'])), font=('', 15)) - LabelPlayerSelect = tk.Label(UpLeftFrame, bg='white', - text=READABLETEXT[49].format(str(dataset[0]['mainset']['PlayerSelect'])), - font=('', 15)) - # 绑定按钮 - LabelPackName.bind('', changePackName) - LabelMusicTitle.bind('', changeMusicTitle) - LabelIsRepeat.bind('', changeIsRepeat) - LabelPlayerSelect.bind('', changePlayerSelect) - # 装入容器 - LabelPackName.pack() - LabelMusicTitle.pack() - LabelIsRepeat.pack() - LabelPlayerSelect.pack() - # 按钮:重置项目设置 - tk.Button(UpLeftFrame, text=READABLETEXT[96], command=ResetSetting).pack() - # 装入窗口 - UpLeftFrame.pack(side='left') - - # 中间的框容器 - UpMidleFrame = tk.Frame(UpFrame, bg='blue') - # 列表 - MusicList_var = tk.StringVar() - ListMusicList = tk.Listbox(UpMidleFrame, listvariable=MusicList_var) - ListMusicList.bind('', MusicList_selected) # 设置选中响应函数 - ListMusicList.pack(side='left') - # 滑块 - tk.Scrollbar(UpMidleFrame, command=ListMusicList.yview).pack(side='left', fill='y') - # 装入窗口 - UpMidleFrame.pack(side='left') - - # 右边的框容器 - UpRightFrame = tk.Frame(UpFrame, bg='white') - # 大标题 - tk.Label(UpRightFrame, text=READABLETEXT[97], font=('', 20)).pack() - # 按钮式文本 - LabelEntityName = tk.Label(UpRightFrame, bg='white', - text=READABLETEXT[42].format(dataset[0]['musics'][NowMusic]['set']['EntityName']), - font=('', 15)) - LabelScoreboardName = tk.Label(UpRightFrame, bg='white', text=READABLETEXT[43].format( - dataset[0]['musics'][NowMusic]['set']['ScoreboardName']), font=('', 15)) - LabelInstrument = tk.Label(UpRightFrame, bg='white', - text=READABLETEXT[44].format(dataset[0]['musics'][NowMusic]['set']['Instrument']), - font=('', 15)) - LabelFileName = tk.Label(UpRightFrame, bg='white', - text=READABLETEXT[45].format(dataset[0]['musics'][NowMusic]['set']['FileName']), - font=('', 15)) - # 绑定按钮 - LabelEntityName.bind('', changeEntityName) - LabelScoreboardName.bind('', changeScoreboardName) - LabelInstrument.bind('', changeInstrument) - LabelFileName.bind('', changeFileName) - # 装入框容器 - LabelEntityName.pack() - LabelScoreboardName.pack() - LabelInstrument.pack() - LabelFileName.pack() - # 按钮:删除选中音轨 - tk.Button(UpRightFrame, text=READABLETEXT[102], command=DelNowMusic).pack() - # 装入窗口 - UpRightFrame.pack(side='left') - - # 上半部分框容器装入窗口 - UpFrame.pack() - - # 下半部分框容器 - DownFrame = tk.Frame(root, bg='blue') - - # 经典名言语录 - import random - texts = open('./resources/myWords.txt', 'r', encoding='utf-8').readlines() - tk.Label(DownFrame, text=texts[random.randint(0, len(texts) - 1)].replace('\n', '').replace('\\n', '\n'), - fg='white', bg='black', font=('DengXian Light', 20)).pack(fill='x') - del texts - - # 音符列表菜单 - NoteList_var = tk.StringVar() - ListNoteList = tk.Listbox(DownFrame, listvariable=NoteList_var, width=40, height=30) - ListNoteList.bind('', NoteList_selected) # 设置选中响应函数 - ListNoteList.pack(side='left') - # 音符列表滑块 - tk.Scrollbar(DownFrame, command=ListNoteList.yview).pack(side='left', fill='y') - - # 指令列表菜单 - ListCMDList = tk.Text(DownFrame, height=37, width=40) - ListCMDList.pack(side='left') - # 指令列表滑块 - tk.Scrollbar(DownFrame, command=ListCMDList.yview).pack(fill='y', side='left') - - # 下半部分容器载入窗口 - DownFrame.pack() - - RefreshMain() - - # 将菜单添加到主窗口中 - root.config(menu=main_menu_bar) - - print('完成!') - - log('启动root.mainloop(窗口)') - - if len(sys.argv) != 1: - log('初始化打开音·创项目' + sys.argv[1]) - global is_save - is_save = True - error = True - try: - with open(sys.argv[1], 'r', encoding='UTF-8') as c: - dataset[0] = json.load(c) - error = False - except OSError: - print(READABLETEXT[8].format(sys.argv[1])) - log('无法打开' + sys.argv[1]) - return - finally: - if error is True: - print(READABLETEXT[8].format(sys.argv[1])) - log('无法打开' + sys.argv[1]) - return - global is_new_file - global ProjectName - is_new_file = False - ProjectName = sys.argv[1] - RefreshMain() - RefreshMusic(NowMusic) - - # 进入窗口消息循环 - root.mainloop() - log('退出') - del filemenu, editmenu, helpmenu, otherMenu - - exitapp() - - -if __name__ == '__main__': - __main__() - -################## - - # def openNewProject(): - # global is_save - # if is_save is not True: - # result = tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[106]) - # if result: - # SaveProject() - # fn = tkinter.filedialog.askopenfilename(title=READABLETEXT[7], initialdir=r'./', - # filetypes=[(READABLETEXT[108], '.msct'), (READABLETEXT[112], '*')], - # multiple=True) - # if fn is None or fn == '': - # return - # else: - # # print(fn) - # fn = fn[0] - # # print(fn) - # log("尝试打开:" + fn) - # try: - # try: - # with open(fn, 'rb') as C: - # global dataset - # # print(pickle.load(C)) - # read = pickle.load(C) # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # # print(read) - # dataset = read[0] - # pkl1 = read[1] - # log("读取新文件成功") - # with open("1.pkl", 'wb') as w: - # pickle.dump(pkl1, w) - # except KeyError: - # with open(fn, 'rb') as C: - # dataset[0] = pickle.load(C) - # log("读取新文件成功") - # except pickle.UnpicklingError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,测试后改为: - # # pickle.UnpicklingError - # print(READABLETEXT[8].format(fn)) - # log('无法打开{}'.format(fn)) - # return - # global is_new_file - # global ProjectName - # is_new_file = False - # ProjectName = fn - # del fn - # global NowMusic - # RefreshMain() - # RefreshMusic(NowMusic) - - # def openClassProject(): - # global is_save - # if is_save is not True: - # result = tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[106]) - # if result: - # SaveProject() - # fn = tkinter.filedialog.askopenfilename(title=READABLETEXT[7], initialdir=r'./', - # filetypes=[(READABLETEXT[108], '.msct'), (READABLETEXT[112], '*')], - # multiple=True) - # if fn is None or fn == '': - # return - # else: - # # print(fn) - # fn = fn[0] - # # print(fn) - # log("尝试打开:" + fn) - # try: - # try: - # with open(fn, 'rb') as C: - # global dataset - # # print(pickle.load(C)) - # read = pickle.load(C) # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! - # # print(read) - # dataset = read - # log("读取新文件成功") - # except KeyError: - # with open(fn, 'rb') as C: - # dataset[0] = pickle.load(C) - # log("读取新文件成功") - # except pickle.UnpicklingError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,测试后改为: - # # pickle.UnpicklingError - # print(READABLETEXT[8].format(fn)) - # log('无法打开{}'.format(fn)) - # return - # global is_new_file - # global ProjectName - # is_new_file = False - # ProjectName = fn - # del fn - # global NowMusic - # RefreshMain() - # RefreshMusic(NowMusic) - - -# ------------------ - # filemenu.add_separator() - # - # filemenu.add_command(label=READABLETEXT[149], command=openNewProject) - # filemenu.add_command(label=READABLETEXT[150], command=SaveNewProject) - # filemenu.add_command(label=READABLETEXT[151], command=SaveAsNewProject) - - # filemenu.add_separator() - # - # filemenu.add_command(label=READABLETEXT[161], command=openClassProject) - # filemenu.add_command(label=READABLETEXT[162], command=SaveClassProject) - # filemenu.add_command(label=READABLETEXT[163], command=SaveAsClassProject) +# -*- coding: utf-8 -*- + + +# W-YI 金羿 +# QQ 2647547478 +# 音·创 开发交流群 861684859 +# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com +# 版权所有 Team-Ryoun 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") +# 若需转载或借鉴 请附作者 + + +""" +音·创 (Musicreater) +一款免费开源的 《我的世界:基岩版》 音乐制作软件 +Musicreater (音·创) +A free opensource software which is used for creating all kinds of musics in Minecraft + + Copyright 2022 Team-Ryoun + + 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. +""" + +# 代码写的并非十分的漂亮,还请大佬多多包涵;本软件源代码依照Apache软件协议公开 + +# -----------------------------分割线----------------------------- +# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日 +# 统计:致命(三级)错误:0个;警告(二级)错误:15个;语法(一级)错误:597个 +# 目前我的Pycharm并没有显示任何错误,有错误可以向 +# bgArray 诸葛亮与八卦阵 +# QQ 474037765 或最好加入:音·创 开发交流群 861684859 +# ------------------------- split line----------------------------- +# Zhuge Liang and Bagua array help to modify the grammar date: -- January 19, 2022 +# Statistics: fatal (Level 3) errors: 0; Warning (Level 2) errors: 15; Syntax (Level 1) error: 597 +# At present, my Pycham does not display any errors. If there are errors, you can report them to me +# Bgarray Zhuge Liang and Bagua array +# QQ 474037765 or better join: Musicreater development exchange group 861684859 +# ------------------------- split line----------------------------- + +# 下面为正文 + + +import json +import os +import shutil +import sys +import threading +import pickle +import tkinter as tk +import tkinter.filedialog +import tkinter.messagebox +import tkinter.simpledialog + +from languages.lang import * +from msctspt.threadOpera import NewThread +from nmcsup.vers import VER + +__version__ = VER[1] + VER[0] +__author__ = '金羿Eilles & 诸葛亮与八卦阵bgArray' + + +print('建立变量,存入内存,载入字典常量函数') + +# 主体部分 + +# 支持多文件同时操作 + +# dataset[{ 'mainset':{ 'x':'y' }, 'musics': [ { 'set' :{ 'A':'B' } , 'note' : [ [ 'a' , b ], ] }, ] }, ] + +# 编辑: +# 修改主设置: dataset[第几个项目]['mainset']['什么设置'] = '设置啥' +# 修改音乐: dataset[第几个项目]['musics'][第几个音轨]['notes'][第几个音符][音符还是时间(0,1)] = 改成啥 +# 修改音轨设置: dataset[第几个项目]['musics'][第几个音轨]['set']['什么设置'] = '设置啥' +# +# 新增音轨: dataset[第几个项目]['musics'].append(datasetmodelpart) +# + + +dataset = [ + { + 'mainset': { + 'ReadMethod': 'old', + 'PackName': 'Ryoun', + 'MusicTitle': 'Noname', + 'IsRepeat': False, + 'PlayerSelect': '' + }, + 'musics': [ + { + 'set': { + 'EntityName': 'MusicSupport', + 'ScoreboardName': 'MusicSupport', + 'Instrument': 'note.harp', + 'FileName': 'Music' + }, + 'notes': [ + + ] + }, + ], + }, +] +'''一个项目中的全部数据。格式参照: +[ + { + 'mainset':{ + 'PackName':'Ryoun', + 'MusicTitle':'Noname', + 'IsRepeat':False, + 'PlayerSelect':'' + }, + 'musics':[ + { + 'set':{ + 'EntityName':'music_support', + 'ScoreboardName':'music_support', + 'Instrument':'harp', + 'FileName':'Music' + }, + 'notes':[ + - Note对象 + 或 + - [MC音调, 持续时间(s)] + ] + }, + ], + }, +] +''' + +is_new_file = True +'''这是否是一个新建的项目?''' + +is_save = True +'''当前项目是否已保存?''' + +ProjectName = '' +'''项目名称,即打开的msct文件名''' + +clearLog = False +'''是否在程序结束时移除日志''' + +NowMusic = 0 +'''当前音轨''' + +root = tk.Tk() +'''主窗口''' + + +def DMM(): # 反回字典用于编辑 + datasetmodelpart = { + 'set': { + 'EntityName': 'MusicSupport', + 'ScoreboardName': 'MusicSupport', + 'Instrument': 'note.harp', + 'FileName': 'Music' + }, + 'notes': [] + } + return datasetmodelpart + + +print('完成') + + +def __main__(): + """音·创 本体\n + W-YI 金羿\n + QQ 2647547478\n + 音·创 开发交流群 861684859\n + Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com\n + 版权所有 Team-Ryoun 金羿\n + 代码根据Apache 2.0 协议开源\n + 若需转载或借鉴 请附作者\n + """ + + print('音·创 正在启动……') + + print('载入日志功能...') + from msctLib.log import log + from nmcsup.log import end + print('完成!') + + print('更新执行位置...') + if sys.platform == 'win32': + try: + os.chdir(__file__[:len(__file__) - __file__[len(__file__)::-1].index('\\')]) + log('更新执行位置,当前文件位置 {}'.format(__file__)) + except FileNotFoundError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,所以既然是pass就随便填一个错误 + pass + else: + try: + os.chdir(__file__[:len(__file__) - __file__[len(__file__)::-1].index('/')]) + except Exception: + pass + log('其他平台:{} 更新执行位置,当前文件位置 {}'.format(sys.platform, __file__)) + print('完成!') + + # 读取文件 + + print('载入文件读取函数') + + def ReadFile(fn: str): # -> list + from nmcsup.nmcreader import ReadFile as fileRead + k = fileRead(fn) + if k is False: + tk.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[105].format(fn)) + return + else: + return k + + # 老的列表读取 + def ReadMidi(midfile: str): # -> str + from nmcsup.nmcreader import ReadMidi as midiRead + k = midiRead(midfile) + if k is False: + tk.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[105].format(midfile)) + return + else: + return k + + # 音色读取 + def LoadMidi(midfile: str): # -> str + from bgArrayLib.reader import midiNewReader + k = midiNewReader(midfile) + if k is False: + tk.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[105].format(midfile)) + return + else: + return k + + # 新的类读取 + def MidiAnalysisClass(midfile: str): + from bgArrayLib.reader import midiClassReader + k = midiClassReader(midfile) + if k is False: + tk.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[105].format(midfile)) + return + else: + return k + + print('完成!') + + # 菜单命令 + print('加载菜单命令...') + + def exitapp(): + global is_save + if is_save is not True: + if tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[106]): + SaveProject() + log('程序正常退出') + + if os.path.isfile("1.pkl"): + os.remove("1.pkl") + + try: + global dataset + del dataset + global root + root.destroy() + del root + except tkinter.TclError: + pass + + if clearLog: + print(READABLETEXT[2]) + # err = True + # try: + end() + if os.path.exists('./log/'): + shutil.rmtree('./log/') + if os.path.exists('./logs/'): + shutil.rmtree('./logs/') + if os.path.exists('./cache/'): + shutil.rmtree('./cache/') + if os.path.exists('./nmcsup/log/'): + shutil.rmtree('./nmcsup/log/') + if os.path.exists('./nmcsup/logs/'): + shutil.rmtree('./nmcsup/logs/') + # err = False + # except: + # print(READABLETEXT[3]) + # + # finally: + # if err is True: + # print(READABLETEXT[3]) + + exit() + + print('退出命令加载完成!') + + def SaveProject(): + global is_save + if is_new_file: + # 新的项目相等于另存为 + SaveAsProject() + return + else: + if dataset[0].get('mainset').get('ReadMethod') == "old": + # 旧项目旧存着吧 + log('存储已有文件:{}'.format(ProjectName)) + with open(ProjectName, 'w', encoding='utf-8') as f: + json.dump(dataset[0], f) + tkinter.messagebox.showinfo(title=READABLETEXT[4], message=READABLETEXT[107].format(ProjectName)) + is_save = True + elif dataset[0].get('mainset').get('ReadMethod') == "class": # 这部分相当SaveClassProject()函数 + # if is_new_file: + # # 新的项目相等于另存为 + # SaveAsClassProject() + # return + # else: + with open(ProjectName, 'wb') as f: + pickle.dump(dataset, f) + tkinter.messagebox.showinfo(title=READABLETEXT[4], + message=READABLETEXT[107].format(ProjectName)) + is_save = True + # return + elif dataset[0].get('mainset').get('ReadMethod') == "new": # 这部分相当于SaveNewProject()函数 + # if is_new_file: # 这部分相当于SaveAsNewProject()函数 + # # 新的项目相等于另存为 + # SaveAsNewProject() + # return + # else: + save_list = [dataset] + try: + with open("1.pkl", 'rb') as r: + save_list.append(pickle.load(r)) + except FileNotFoundError: + pass + with open(ProjectName, 'wb') as f: + pickle.dump(save_list, f) + tkinter.messagebox.showinfo(title=READABLETEXT[4], + message=READABLETEXT[107].format(ProjectName)) + is_save = True + return + + print('保存项目命令加载完成!') + + def SaveAsProject(): + global is_save + if dataset[0].get('mainset').get('ReadMethod') == "old": + # 另存为项目 + fn = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[5], initialdir=r'./', + filetypes=[(READABLETEXT[108][0], '.msct'), + (READABLETEXT[109], '*')], + defaultextension='Noname.msct') + if fn is None or fn == '': + return + try: + Project_Name = fn + with open(Project_Name, 'w', encoding='utf-8') as f: + json.dump(dataset[0], f) + tkinter.messagebox.showinfo(title=READABLETEXT[4], message=READABLETEXT[107].format(Project_Name)) + is_save = True + except TypeError: + Project_Name = fn + with open(Project_Name, 'wb') as f: + pickle.dump(dataset[0], f) + tkinter.messagebox.showinfo(title=READABLETEXT[4], message=READABLETEXT[107].format(Project_Name)) + is_save = True + elif dataset[0].get('mainset').get('ReadMethod') == "class": # 等于SaveAsNewProject()函数 + fn = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[5], initialdir=r'./', + filetypes=[(READABLETEXT[108][1], '.msctn'), + (READABLETEXT[109], '*')], + defaultextension='Noname.msctn') + if fn is None or fn == '': + return + Project_Name = fn + with open(Project_Name, 'wb') as f: + pickle.dump(dataset, f) + tkinter.messagebox.showinfo(title=READABLETEXT[4], message=READABLETEXT[107].format(Project_Name)) + + is_save = True + elif dataset[0].get('mainset').get('ReadMethod') == "new": # 等于SaveAsClassProject()函数 + fn = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[5], initialdir=r'./', + filetypes=[(READABLETEXT[108][2], '.msctx'), + (READABLETEXT[109], '*')], + defaultextension='Noname.msctx') + if fn is None or fn == '': + return + Project_Name = fn + save_list = [dataset] + try: + with open("1.pkl", 'rb') as r: + save_list.append(pickle.load(r)) + except FileNotFoundError: + pass + print(save_list) + with open(Project_Name, 'wb') as f: + pickle.dump(save_list, f) + tkinter.messagebox.showinfo(title=READABLETEXT[4], message=READABLETEXT[107].format(Project_Name)) + is_save = True + + print('另存项目命令加载完成!') + + def openOldProject(): + global is_save + if is_save is not True: + result = tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[106]) + if result: + SaveProject() + fn = tkinter.filedialog.askopenfilename(title=READABLETEXT[6], initialdir=r'./', + filetypes=[(READABLETEXT[110], '.ry.nfc'), + (READABLETEXT[111], '.ry.mfm'), (READABLETEXT[112], '*')], + multiple=True) + if fn is None or fn == '': + return + else: + fn = fn[0] + from nmcsup.nmcreader import ReadOldProject + dataset[0] = ReadOldProject(fn) + + def openProject(): + global is_save + global dataset + if is_save is not True: + result = tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[106]) + if result: + SaveProject() + fn = tkinter.filedialog.askopenfilename(title=READABLETEXT[7], initialdir=r'./', + filetypes=[(READABLETEXT[108][0], '.msct'), + (READABLETEXT[108][1], '.msctn'), # msctn: 音创新文件(用类方法解析) + (READABLETEXT[108][2], '.msctx'), # msctx: 音创测试文件(用来支持多乐器解析) + (READABLETEXT[112], '*')], + multiple=True) + if fn is None or fn == '': + return + else: + fn = fn[0] + log("尝试打开:" + fn) + if str(fn)[str(fn).rfind("."):] == ".msct": # str(fn)[str(fn).rfind("."):] ->文件格式返回".xxx" + try: + try: + with open(fn, 'r', encoding='UTF-8') as C: + dataset[0] = json.load(C) + log("读取工程文件成功") + except UnicodeDecodeError: + print(READABLETEXT[8].format(fn)) + log('无法打开{}'.format(fn)) + return + except json.decoder.JSONDecodeError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,测试后改为: + # json.decoder.JSONDecodeError + print(READABLETEXT[8].format(fn)) + log('无法打开{}'.format(fn)) + return + elif str(fn)[str(fn).rfind("."):] == ".msctx": + try: + try: + with open(fn, 'rb') as C: + # print(pickle.load(C)) + read = pickle.load(C) # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # print(read) + dataset = read[0] + pkl1 = read[1] + log(f"读取新文件成功:\n{str(dataset[0])}") + with open("1.pkl", 'wb') as w: + pickle.dump(pkl1, w) + except KeyError: + with open(fn, 'rb') as C: + dataset[0] = pickle.load(C) + log(f"读取新文件成功:\n{str(dataset[0])}") + except pickle.UnpicklingError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,测试后改为: + # pickle.UnpicklingError + print(READABLETEXT[8].format(fn)) + log('无法打开{}'.format(fn)) + return + elif str(fn)[str(fn).rfind("."):] == ".msctn": + try: + try: + with open(fn, 'rb') as C: + # print(pickle.load(C)) + read = pickle.load(C) # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # print(read) + dataset = read + log("读取新文件成功") + except KeyError: + with open(fn, 'rb') as C: + dataset[0] = pickle.load(C) + log("读取新文件成功") + except pickle.UnpicklingError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,测试后改为: + # pickle.UnpicklingError + print(READABLETEXT[8].format(fn)) + log('无法打开{}'.format(fn)) + return + else: + return + global is_new_file + global ProjectName + is_new_file = False + ProjectName = fn + del fn + global NowMusic + RefreshMain() + RefreshMusic(NowMusic) + + print('打开项目命令加载完成!') + + def appabout(): + aabw = tk.Tk() + aabw.title(READABLETEXT[9]) + aabw.geometry('550x600') # 像素 + tk.Label(aabw, text='', font=('', 15)).pack() + tk.Label(aabw, text=READABLETEXT[10], font=('', 35)).pack() + tk.Label(aabw, text=READABLETEXT[11].format(VER[1] + VER[0]), font=('', 15)).pack() + # pack 的side可以赋值为LEFT RTGHT TOP BOTTOM + # grid 的row 是列数、column是行排,注意,这是针对空间控件本身大小来的,即是指向当前控件的第几个。 + # place的 x、y是(x,y)坐标 + # pic = tk.PhotoImage(file='./bin/pics/Ryoun_S.png') + # tk.Label(aabw, image=pic, width=200, height=200).pack() + # del pic + tk.Label(aabw, text='', font=('', 5)).pack() + tk.Label(aabw, text=READABLETEXT[12], font=('', 20)).pack() + tk.Label(aabw, text='', font=('', 15)).pack() + for i in READABLETEXT[15]: + tk.Label(aabw, text=i[0], font=('', 17 if i[1] else 15, 'bold' if i[1] else '')).pack() + tk.Label(aabw, text='', font=('', 5)).pack() + if DEFAULTLANGUAGE != 'zh-CN': + tk.Label(aabw, text=READABLETEXT[16], font=('', 15)).pack() + for i in READABLETEXT['Translator']: + tk.Label(aabw, text=i[0], font=('', 17 if i[1] else 15, 'bold' if i[1] else '')).pack() + + def exitAboutWindow(): + aabw.destroy() + + tk.Button(aabw, text=READABLETEXT[13], command=exitAboutWindow).pack() + + aabw.mainloop() + + print('关于命令加载完成!') + + def apphelp(): + def funcHelp(): + funTK = tk.Tk() + funTK.title("函数功能查询") + funTK.geometry('1200x1000') + thingLabel = tk.Label(funTK, text="函数功能查询", font=('', 20)) + thingLabel.pack() + aLabel = tk.Label(funTK, text="""文件:\n + 打开音·创项目...: 打开三种类型的音创文件(.msct, .msctn, .msctx)\n + 打开旧项目...: 打开两种类型的音创文件(.ry.nfc, .ry.mfm)\n + 保存项目: 自动选择保存类型,并保存为音创文件(.msct, .msctn, .msctx)\n + 另存为...: 自动选择另存为类型,并保存为音创文件(.msct, .msctn, .msctx)\n + 退出 : 退出程序\n\n + 编辑:\n + 从midi导入音轨: 以旧方法(列表方法)解析midi,如果你使用这个方法解析,意味着你选择.msct文件\n + 从midi导入音轨且用新方法解析: 以新方法(类方法)解析midi,并解析乐器信息,如果你使用这个方法解析,意味着你选择.msctx文件\n + 注意!!!这个功能暂时只用于支持雪莹乐器资源包,如果你不是为了这个,最好别用!\n + 从midi导入音轨且用类方法解析: 以类方法解析midi,如果你使用这个方法解析,意味着你选择.msctn文件\n + 注意!!!这个功能暂时在开发中!!!别用!\n + """, font=('宋体', 12)) + aLabel.pack() + + ahpw = tk.Tk() + ahpw.title(READABLETEXT[19]) + ahpw.geometry('400x600') # 像素 + tk.Label(ahpw, text="帮助", font=('楷体', 32)).grid(row=0, column=2) + tk.Button(ahpw, text="函数功能查询", command=funcHelp, font=('楷体', 20)).grid(row=1, column=1) + ahpw.mainloop() + + print('帮助命令加载完成!') + + def FromMP3(): + log('从MP3导入音乐') + mp3file = tkinter.filedialog.askopenfilename(title=READABLETEXT[20], initialdir=r'./', + filetypes=[(READABLETEXT[113], '.mp3 .m4a'), + (READABLETEXT[112], '*')], multiple=True) + if mp3file is None or mp3file == '': + log('取消') + return + else: + mp3file = mp3file[0] + from nmcsup.nmcreader import ReadMidi + from nmcsup.trans import Mp32Mid + if not os.path.exists('./Temp/'): + os.makedirs('./Temp/') + Mp32Mid(mp3file, './Temp/Trans.mid') + log('打开midi文件./Temp/Trans.mid') + th = NewThread(ReadMidi, ('./Temp/Trans.mid',)) + th.start() + del mp3file + + 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 + global NowMusic + RefreshMain() + RefreshMusic(NowMusic) + + threading.Thread(target=midiSPT, args=(th,)).start() + del th + + print('读MP3加载完成') + + def FromListMidi(): + log('从midi导入音乐') + midfile = tkinter.filedialog.askopenfilename(title=READABLETEXT[21], initialdir=r'./', + filetypes=[(READABLETEXT[114], '.mid .midi'), + (READABLETEXT[112], '*')], multiple=True) + if midfile is None or midfile == '': + log('取消') + return + else: + midfile = midfile[0] + th = NewThread(ReadMidi, (midfile,)) + th.start() + del midfile + + def midiSPT(th_): + try: + try: + for i in th_.getResult(): + datas = DMM() + datas['notes'] = i + dataset[0]['musics'].append(datas) + del th_ + global is_save + is_save = False + global NowMusic + RefreshMain() + RefreshMusic(NowMusic) + except OSError: + tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) + except AttributeError: + try: + tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) + except OSError: + tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) + + threading.Thread(target=midiSPT, args=(th,)).start() + del th + + def FromNewMidi(): + log('从midi导入音乐并采用新读取方式') + midfile = tkinter.filedialog.askopenfilename(title=READABLETEXT[21], initialdir=r'./', + filetypes=[(READABLETEXT[114], '.mid .midi'), + (READABLETEXT[112], '*')], multiple=True) + if midfile is None or midfile == '': + log('取消') + return + else: + midfile = midfile[0] + th = NewThread(LoadMidi, (midfile,)) + th.start() + del midfile + + def midiSPT(th_): + try: + try: + for i in th_.getResult(): + datas = DMM() + datas['notes'] = i + dataset[0]['musics'].append(datas) + del th_ + global is_save + is_save = False + global NowMusic + RefreshMain() + RefreshMusic(NowMusic) + except OSError: + tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) + except AttributeError: + try: + tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) + except OSError: + tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[167]) + + threading.Thread(target=midiSPT, args=(th,)).start() + del th + dataset[0]['mainset']['ReadMethod'] = "new" + + def FromClassMidi(): + log('从midi导入音乐并采用类读取方式') + midfile = tkinter.filedialog.askopenfilename(title=READABLETEXT[21], initialdir=r'./', + filetypes=[(READABLETEXT[114], '.mid .midi'), + (READABLETEXT[112], '*')], multiple=True) + if midfile is None or midfile == '': + log('取消') + return + else: + midfile = midfile[0] + th = NewThread(MidiAnalysisClass, (midfile,)) + th.start() + del midfile + + 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 + global NowMusic + RefreshMain() + RefreshMusic(NowMusic) + threading.Thread(target=midiSPT, args=(th,)).start() + del th + dataset[0]['mainset']['ReadMethod'] = "class" + + print('读midi命令加载完成!') + + def FromForm(): + log('从文本读入音轨') + fn = tkinter.filedialog.askopenfilename(title=READABLETEXT[22], initialdir=r'./', + filetypes=[(READABLETEXT[115], '.txt'), (READABLETEXT[112], '*')], + multiple=True) + if fn is None or fn == '': + log('取消') + return + else: + fn = fn[0] + th = NewThread(ReadFile, (fn,)) + 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 + global NowMusic + RefreshMain() + RefreshMusic(NowMusic) + + threading.Thread(target=midiSPT, args=(th,)).start() + + print('读txt命令加载完成!') + + def FromText(): + log('写入音符至音轨') + dat = tkinter.simpledialog.askstring(title=READABLETEXT[23], prompt=READABLETEXT[14], initialvalue='`1 .2 C') + if dat is None: + return + datas = [] + for i in dat.split(' '): + datas.append([str(i), 1.0]) + log(READABLETEXT[24].format(str(datas))) + from nmcsup.trans import note2list + datat = DMM() + datat['notes'] = note2list(datas) + dataset[0]['musics'].append(datat) + del datas, datat, dat + global is_save + is_save = False + global NowMusic + RefreshMain() + RefreshMusic(NowMusic) + + print('写入命令加载完成!') + print('开始加载列表生成函数函数。') + + def ShowCMD(): + log('展示指令') + global NowMusic + from nmcsup.trans import Note2Cmd + RefreshCMDList( + Note2Cmd(dataset[0]['musics'][NowMusic]['notes'], dataset[0]['musics'][NowMusic]['set']['ScoreboardName'], + dataset[0]['musics'][NowMusic]['set']['Instrument'], dataset[0]['mainset']['PlayerSelect'])) + + def MakeCMD(): + log('生成文件') + from msctspt.funcOpera import makeFuncFiles + file = tkinter.filedialog.askdirectory(title=READABLETEXT[25], initialdir=r'./') + if file is None or file == '': + log('取消') + return + else: + makeFuncFiles(dataset[0], file + '/') + + def MakeCMDdir(): + log('生成函数包') + from msctspt.funcOpera import makeFunDir + file = tkinter.filedialog.askdirectory(title=READABLETEXT[26], initialdir=r'./') + if file is None or file == '': + log('取消') + return + else: + makeFunDir(dataset[0], file + '/') + + def MakePackFile(): + file = tkinter.filedialog.askdirectory(title=READABLETEXT[27], initialdir=r'./') + if file is None or file == '': + log('取消') + return + import zipfile + + from msctspt.funcOpera import makeFunDir + log('生成附加包文件') + if not os.path.exists('./temp/'): + os.makedirs('./temp/') + makeFunDir(dataset[0], './temp/') + + shutil.move('./temp/{}Pack/behavior_packs/{}/functions'.format(dataset[0]['mainset']['PackName'], + dataset[0]['mainset']['PackName']), './') + + shutil.move('./temp/{}Pack/behavior_packs/{}/manifest.json'.format(dataset[0]['mainset']['PackName'], + dataset[0]['mainset']['PackName']), './') + + with zipfile.ZipFile('{}/{}.mcpack'.format(file, dataset[0]['mainset']['PackName']), 'w') as zipobj: + for i in os.listdir('./functions/'): + zipobj.write('./functions/{}'.format(i)) + zipobj.write('./manifest.json') + shutil.move('./functions', './temp/') + shutil.move('./manifest.json', './temp/') + shutil.rmtree('./temp/') + + print('完成加载列表生成函数函数。') + print('开始加载乐器类生成函数函数。') + + def MakeNewCMD(): + log('生成新文件') + from msctspt.funcOpera import makeNewFuncFiles + file = tkinter.filedialog.askdirectory(title=READABLETEXT[25], initialdir=r'./') + if file is None or file == '': + log('取消') + return + else: + makeNewFuncFiles(dataset[0], file + '/') + + def MakeNewCMDdir(): + log('生成新函数包与材质包') + from msctspt.funcOpera import makeNewFunDir + file = tkinter.filedialog.askdirectory(title=READABLETEXT[26], initialdir=r'./') + if file is None or file == '': + log('取消') + return + else: + makeNewFunDir(dataset[0], file + '/') + + def MakeNewFunctionPackFile(): + file = tkinter.filedialog.askdirectory(title=READABLETEXT[27], initialdir=r'./') + if file is None or file == '': + log('取消') + return + import zipfile + + from msctspt.funcOpera import makeNewFunDir + log('生成附加包文件') + if not os.path.exists('./temp/'): + os.makedirs('./temp/') + makeNewFunDir(dataset[0], './temp/') + + shutil.move('./temp/{}Pack/behavior_packs/{}/functions'.format(dataset[0]['mainset']['PackName'], + dataset[0]['mainset']['PackName']), './') + + shutil.move('./temp/{}Pack/behavior_packs/{}/manifest.json'.format(dataset[0]['mainset']['PackName'], + dataset[0]['mainset']['PackName']), './') + + with zipfile.ZipFile('{}/{}.mcpack'.format(file, dataset[0]['mainset']['PackName']), 'w') as zipobj: + for i in os.listdir('./functions/'): + zipobj.write('./functions/{}'.format(i)) + zipobj.write('./manifest.json') + shutil.move('./functions', './temp/') + shutil.move('./manifest.json', './temp/') + shutil.rmtree('./temp/') + + def MakeNewFunctionPack_ResourcesPacks_File(): # 这个是直接复制资源包(散包) + file = tkinter.filedialog.askdirectory(title=READABLETEXT[27], initialdir=r'./') + if file is None or file == '': + log('取消') + return + from bgArrayLib.sy_resourcesPacker import resources_pathSetting + result = resources_pathSetting() + print(result) + if result[0] is False: + if result[1] == 1: + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[157]) + if result[1] == 2: + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[158]) + return + else: + import zipfile + + from msctspt.funcOpera import makeNewFunDir + log('生成附加包文件') + if not os.path.exists('./temp/'): + os.makedirs('./temp/') + makeNewFunDir(dataset[0], './temp/') + + shutil.move('./temp/{}Pack/behavior_packs/{}/functions'.format(dataset[0]['mainset']['PackName'], + dataset[0]['mainset']['PackName']), './') + + shutil.move('./temp/{}Pack/behavior_packs/{}/manifest.json'.format(dataset[0]['mainset']['PackName'], + dataset[0]['mainset']['PackName']), './') + + with zipfile.ZipFile('{}/{}.mcpack'.format(file, dataset[0]['mainset']['PackName']), 'w') as zipobj: + for i in os.listdir('./functions/'): + zipobj.write('./functions/{}'.format(i)) + zipobj.write('./manifest.json') + shutil.move('./functions', './temp/') + shutil.move('./manifest.json', './temp/') + shutil.rmtree('./temp/') + from bgArrayLib.sy_resourcesPacker import scatteredPack + scatteredPack(file) + + print('完成加载乐器类生成函数函数。') + print('开始加载乐器音色资源绑定函数。') + + def changeResourcesPath(): + file = tkinter.filedialog.askdirectory(title=READABLETEXT[27], initialdir=r'./') + if file is None or file == '': + log('取消') + return + from bgArrayLib.sy_resourcesPacker import resources_pathSetting + result = resources_pathSetting(file) + print(result) + if result[0] is False: + if result[1] == 1: + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[157]) + if result[1] == 2: + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[158]) + else: + tkinter.messagebox.showinfo(title=READABLETEXT[1], message=READABLETEXT[159]) + + print('开始加载类生成函数函数。') + + def MakeClassCMD(): + log('生成类文件') + from msctspt.funcOpera import makeClassFuncFiles + file = tkinter.filedialog.askdirectory(title=READABLETEXT[25], initialdir=r'./') + if file is None or file == '': + log('取消') + return + else: + makeClassFuncFiles(dataset[0], file + '/') + + def MakeClassCMDdir(): + log('生成类函数包与材质包') + from msctspt.funcOpera import makeClassFunDir + file = tkinter.filedialog.askdirectory(title=READABLETEXT[26], initialdir=r'./') + if file is None or file == '': + log('取消') + return + else: + makeClassFunDir(dataset[0], file + '/') + + def MakeClassFunctionPackFile(): + file = tkinter.filedialog.askdirectory(title=READABLETEXT[27], initialdir=r'./') + if file is None or file == '': + log('取消') + return + import zipfile + + from msctspt.funcOpera import makeClassFunDir + log('生成附加包文件') + if not os.path.exists('./temp/'): + os.makedirs('./temp/') + makeClassFunDir(dataset[0], './temp/') + + shutil.move('./temp/{}Pack/behavior_packs/{}/functions'.format(dataset[0]['mainset']['PackName'], + dataset[0]['mainset']['PackName']), './') + + shutil.move('./temp/{}Pack/behavior_packs/{}/manifest.json'.format(dataset[0]['mainset']['PackName'], + dataset[0]['mainset']['PackName']), './') + + with zipfile.ZipFile('{}/{}.mcpack'.format(file, dataset[0]['mainset']['PackName']), 'w') as zipobj: + for i in os.listdir('./functions/'): + zipobj.write('./functions/{}'.format(i)) + zipobj.write('./manifest.json') + shutil.move('./functions', './temp/') + shutil.move('./manifest.json', './temp/') + shutil.rmtree('./temp/') + + print('完成加载类生成函数函数。') + print('开始加载地图函数。') + + # 转为空方块世界 + def ToBlockWorldEpt(): + import zipfile + global dire + + from nmcsup.trans import Cmd2World, Datas2BlkWorld, Notes2Player + while True: + try: + dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], + initialvalue='16 4 16') + if dire is None or dire == '': + return + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') + if Outdire is None or Outdire == '': + log('取消') + return + else: + Outdire = '{}/{}/'.format(Outdire[0], dataset[0]['mainset']['PackName']) + with zipfile.ZipFile('./nmcsup/EptWorld.zip') as zipobj: # , 'r' (参数等于默认时不写) + zipobj.extractall(Outdire) + NoteData = [] + for i in dataset[0]['musics']: + NoteData.append(i['notes']) + Datas2BlkWorld(NoteData, Outdire, dire) + del NoteData + for i in range(len(dataset[0]['musics'])): + Cmd2World(Notes2Player(dataset[0]['musics'][i]['notes'], [dire[0], dire[1], dire[2] + i], + {'Ent': dataset[0]['musics'][i]['set']['EntityName'], + 'Pls': dataset[0]['mainset']['PlayerSelect'], + 'Ins': dataset[0]['musics'][i]['set']['Instrument']}), Outdire, + [dire[0] - 5 - i, dire[1], dire[2]]) + del dire, Outdire + + # 转为已存在的方块世界 + def ToBlockWorld(): + from nmcsup.trans import Cmd2World, Datas2BlkWorld, Notes2Player + global dire + while True: + try: + dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], + initialvalue='16 4 16') + if dire is None or dire == '': + return + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') + if Outdire is None or Outdire == '': + log('取消') + return + else: + Outdire += '/' + NoteData = [] + for i in dataset[0]['musics']: + NoteData.append(i['notes']) + Datas2BlkWorld(NoteData, Outdire, dire) + del NoteData + for i in range(len(dataset[0]['musics'])): + Cmd2World(Notes2Player(dataset[0]['musics'][i]['notes'], [dire[0], dire[1], dire[2] + i], + {'Ent': dataset[0]['musics'][i]['set']['EntityName'], + 'Pls': dataset[0]['mainset']['PlayerSelect'], + 'Ins': dataset[0]['musics'][i]['set']['Instrument']}), Outdire, + [dire[0] - 5 - i, dire[1], dire[2]]) + del dire, Outdire + + # 生成函数播放器 + def MakeFuncPlayer(): + global dire + while True: + try: + dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], + initialvalue='16 4 16') + if dire is None or dire == '': + return + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[30], initialdir=r'./') + if Outdire is None or Outdire == '': + return + else: + Outdire = '{}/{}/'.format(Outdire, dataset[0]['mainset']['PackName']) + from nmcsup.trans import Notes2Player + for i in range(len(dataset[0]['musics'])): + open(Outdire + dataset[0]['musics'][i]['set']['FileName'] + '_' + str(i) + '.mcfunction', 'w', + encoding='utf-8').writelines( + Notes2Player(dataset[0]['musics'][i]['notes'], [dire[0], dire[1], dire[2] + i], + {'Ent': dataset[0]['musics'][i]['set']['EntityName'], + 'Pls': dataset[0]['mainset']['PlayerSelect'], + 'Ins': dataset[0]['musics'][i]['set']['Instrument']})) + + # 转为空指令世界 + def ToCmdWorldEpt(): + import zipfile + global dire + + from nmcsup.trans import Cmd2World, Note2Cmd + while True: + try: + dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], + initialvalue='16 4 16') + if dire is None or dire == '': + return + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') + if Outdire is None or Outdire == '': + return + else: + Outdire += '/' + dataset[0]['mainset']['PackName'] + '/' + with zipfile.ZipFile('./nmcsup/EptWorld.zip') as zipobj: # , 'r' (默认参数不用设置) + zipobj.extractall(Outdire) + for i in range(len(dataset[0]['musics'])): + Cmd2World(Note2Cmd(dataset[0]['musics'][i]['notes'], dataset[0]['musics'][i]['set']['ScoreboardName'], + dataset[0]['musics'][i]['set']['Instrument'], dataset[0]['mainset']['PlayerSelect'], + True), Outdire, [dire[0], dire[1], dire[2] + i]) + del dire, Outdire + + # 转为已存在的指令世界 + def ToCmdWorld(): + global dire + from nmcsup.trans import Cmd2World, Note2Cmd + while True: + try: + dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], + initialvalue='16 4 16') + if dire is None or dire == '': + return + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') + if Outdire is None or Outdire == '': + return + else: + Outdire += '/' + for i in range(len(dataset[0]['musics'])): + Cmd2World(Note2Cmd(dataset[0]['musics'][i]['notes'], dataset[0]['musics'][i]['set']['ScoreboardName'], + dataset[0]['musics'][i]['set']['Instrument'], dataset[0]['mainset']['PlayerSelect'], + True), Outdire, [dire[0], dire[1], dire[2] + i]) + del dire, Outdire + + # 函数输入指令块 + def func2World(): + from nmcsup.trans import Cmd2World + global dire + while True: + try: + dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], + initialvalue='16 4 16') + if dire is None or dire == '': + return + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') + if Outdire is None or Outdire == '': + return + else: + Outdire += '/' + Cmd2World(open(tkinter.filedialog.askopenfilename(title=READABLETEXT[31], initialdir=r'./', + filetypes=[(READABLETEXT[118], '.mcfunction'), + (READABLETEXT[112], '*')], multiple=True)[0], 'r', + encoding='utf-8').readlines(), Outdire, dire) + + # 大函数分割并载入执行链 + def bigFunc2World(): + log('分割大函数') + global dire + import uuid + + from msctspt.funcOpera import funSplit + from msctspt.transfer import hans2pinyin + from nmcsup.trans import Cmd2World + while True: + try: + dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[119], + initialvalue='16 4 16') + if dire is None or dire == '': + return + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') + if Outdire is None or Outdire == '': + log('取消') + return + else: + Outdire += '/' + log('获得地图地址:' + Outdire) + fileName = tkinter.filedialog.askopenfilename(title=READABLETEXT[31], initialdir=r'./', + filetypes=[(READABLETEXT[118], '.mcfunction'), + (READABLETEXT[112], '*')], multiple=True) + if fileName is None or fileName == '': + log('取消') + return + else: + fileName = fileName[0] + log('获得文件名:' + fileName) + bigFile = open(fileName, 'r', encoding='utf-8') + parts = funSplit(bigFile) + if parts == -1: + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[121]) + return + log('创建函数文件夹') + packName = fileName[len(fileName) - fileName[::-1].index('/'):fileName.index('.')] + packDire = hans2pinyin(packName) + try: + os.makedirs(Outdire + 'behavior_packs/' + packDire + '/functions/') + except FileExistsError: + log('已存在文件夹') + log('创建manifest.json以及world_behavior_packs.json') + behaviorUuid = uuid.uuid4() + if os.path.exists(Outdire + 'world_behavior_packs.json'): + with open(Outdire + 'world_behavior_packs.json', 'r') as f: + have = json.load(f) + have.append({'pack_id': str(behaviorUuid), 'version': [0, 0, 1]}) + with open(Outdire + 'world_behavior_packs.json', 'w', encoding='utf-8') as f: + json.dump(have, f) + del have + else: + with open(Outdire + 'world_behavior_packs.json', 'w', encoding='utf-8') as f: + f.write('[\n {\'pack_id\': \'' + str(behaviorUuid) + '\',\n \'version\': [ 0, 0, 1 ]}\n]') + with open(Outdire + 'behavior_packs/' + packDire + '/manifest.json', 'w') as f: + f.write( + '{\n \'format_version\': 1,\n \'header\': {\n \'description\': \'' + packName + + ' Pack : behavior pack\',\n \'version\': [ 0, 0, 1 ],\n \'name\': \'' + packName + + 'Pack\',\n \'uuid\': \'' + str( + behaviorUuid) + '\'\n },\n \'modules\': [\n {\n \'description\': \'' + packName + + ' Pack : behavior pack\',\n \'type\': ' + '\'data\',\n \'version\': [ 0, 0, 1 ],\n \'uuid\': \'' + str( + uuid.uuid4()) + '\'\n }\n ]\n}') # 要求文段不能过长 + cmdlist = [] + for i in parts: + open(Outdire + 'behavior_packs/' + packDire + '/functions/' + packDire + str( + parts.index(i) + 1) + '.mcfunction', 'w', encoding='utf-8').writelines(i) + cmdlist.append('function ' + packDire + str(parts.index(i) + 1)) + Cmd2World(cmdlist, Outdire, dire) + del cmdlist, behaviorUuid, Outdire, fileName, bigFile, parts, dire, packName, packDire + + def toScbBDXfile(): + log('单音轨转BDX') + from msctspt.transfer import note2bdx + global dire + while True: + try: + dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[122], + initialvalue='0 0 0') + if dire is None or dire == '': + return + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + + fileName = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[32], initialdir=r'./', + filetypes=[(READABLETEXT[123], '.bdx'), + (READABLETEXT[112], '*')], + defaultextension=dataset[0]['mainset']['PackName'] + '.bdx', + initialfile=dataset[0]['mainset']['PackName'] + '.bdx') + if fileName is None or fileName == '': + log('取消') + return + + log('获得文件名:' + fileName) + + res = note2bdx(fileName, dire, dataset[0]['musics'][NowMusic]['notes'], + dataset[0]['musics'][NowMusic]['set']['ScoreboardName'], + dataset[0]['musics'][NowMusic]['set']['Instrument'], dataset[0]['mainset']['PlayerSelect']) + log('转换结束!\n' + str(res)) + tkinter.messagebox.showinfo(READABLETEXT[33], READABLETEXT[124].format(str(res))) + + def toBDXfile(): + log('整首歌转BDX') + from msctspt.transfer import music2BDX + global dire + while True: + try: + dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[122], + initialvalue='0 0 0') + if dire is None or dire == '': + return + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + + fileName = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[32], initialdir=r'./', + filetypes=[(READABLETEXT[123], '.bdx'), + (READABLETEXT[112], '*')], + defaultextension=dataset[0]['mainset']['PackName'] + '.bdx', + initialfile=dataset[0]['mainset']['PackName'] + '.bdx') + + maxHeight = 200 + + while True: + maxHeight = tkinter.simpledialog.askinteger(title=READABLETEXT[28], + prompt=READABLETEXT[93], + initialvalue='200') + if maxHeight >= 5: + break + elif maxHeight is None: + log('取消') + return + else: + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[94]) + continue + + if fileName is None or fileName == '': + log('取消') + return + + log('获得文件名:' + fileName) + + res = music2BDX(fileName, dire, dataset[0], height = maxHeight ) + log('转换结束!\n' + str(res)) + tkinter.messagebox.showinfo(READABLETEXT[33], READABLETEXT[124].format(str(res))) + + def wsPlay(): + from msctspt.transfer import note2webs + spd = tkinter.simpledialog.askfloat(READABLETEXT[34], prompt=READABLETEXT[125], initialvalue='5.0') + tkinter.messagebox.showinfo(title=READABLETEXT[35], message=READABLETEXT[126]) + note2webs(dataset[0]['musics'][NowMusic]['notes'], dataset[0]['musics'][NowMusic]['set']['Instrument'], spd, + dataset[0]['mainset']['PlayerSelect']) + + def toRSworldEPT(): + import zipfile + global dire + dire = "" + + from msctspt.transfer import note2RSworld + while True: + try: + dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], + initialvalue='16 4 16') + if dire is None or dire == '': + return + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') + if Outdire is None or Outdire == '': + return + else: + Outdire += '/' + dataset[0]['mainset']['PackName'] + '/' + with zipfile.ZipFile('./nmcsup/EptWorld.zip') as zipobj: # , 'r'(默认参数不用写) + zipobj.extractall(Outdire) + for i in range(len(dataset[0]['musics'])): + note2RSworld(Outdire, dire, dataset[0]['musics'][i]['notes'], dataset[0]['musics'][i]['set']['Instrument']) + + del dire, Outdire + + def toRSworld(): + from msctspt.transfer import note2RSworld + global dire + dire = "" + while True: + try: + dire = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[116], + initialvalue='16 4 16') + if dire is None or dire == '': + return + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + Outdire = tkinter.filedialog.askdirectory(title=READABLETEXT[29], initialdir=r'./') + if Outdire is None or Outdire == '': + return + else: + Outdire += '/' + for i in range(len(dataset[0]['musics'])): + note2RSworld(Outdire, dire, dataset[0]['musics'][i]['notes'], dataset[0]['musics'][i]['set']['Instrument']) + del dire, Outdire + + def world2RyStruct(): + global begp + global endp + outdir = tkinter.filedialog.askdirectory(title=READABLETEXT[36], initialdir=r'./') + if outdir is None or outdir == '': + return + else: + outdir += '/' + while True: + try: + begp = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[127], + initialvalue='16 4 16') + if begp is None or begp == '': + return + begp = [int(begp.split(' ')[0]), int(begp.split(' ')[1]), int(begp.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + while True: + try: + endp = tkinter.simpledialog.askstring(title=READABLETEXT[28], prompt=READABLETEXT[128], + initialvalue='16 4 16') + if endp is None or endp == '': + return + endp = [int(endp.split(' ')[0]), int(endp.split(' ')[1]), int(endp.split(' ')[2])] + except ValueError: # 测试完为ValueError,故修改语法 + tkinter.messagebox.showerror(title=READABLETEXT[0], message=READABLETEXT[117]) + continue + break + isAir = tkinter.messagebox.askyesno(READABLETEXT[37], READABLETEXT[129]) + fileName = tkinter.filedialog.asksaveasfilename(title=READABLETEXT[38], initialdir=r'./', + filetypes=[(READABLETEXT[130], '.RyStruct'), + (READABLETEXT[112], '*')], + defaultextension='*.RyStruct', initialfile='*.RyStruct') + if fileName is None or fileName == '': + log('取消') + return + from msctspt.transfer import ryStruct + rys = ryStruct(outdir) + rys.world2Rys(begp, endp, isAir) + # error1 = True + try: + with open(fileName, 'w', encoding='utf-8') as f: + json.dump(rys.RyStruct, f, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False) + tkinter.messagebox.showinfo(READABLETEXT[33], READABLETEXT[131].format(fileName)) + # error1 = False + except: + tkinter.messagebox.showerror(READABLETEXT[39], READABLETEXT[132].format(fileName, str(rys.RyStruct))) + rys.closeLevel() + # finally: + # if error1 is True: + # tkinter.messagebox.showerror(READABLETEXT[39], READABLETEXT[132].format(fileName, str(rys.RyStruct))) + # rys.closeLevel() + + def world2BDX(): + tkinter.messagebox.showerror(READABLETEXT[0], READABLETEXT[133]) + + # 使用邮件反馈bug + def sendBugReport(): + from msctspt.bugReporter import report + name = tkinter.simpledialog.askstring(title=READABLETEXT[40], prompt=READABLETEXT[134]) + contact = tkinter.simpledialog.askstring(title=READABLETEXT[40], prompt=READABLETEXT[135]) + describetion = tkinter.simpledialog.askstring(title=READABLETEXT[40], prompt=READABLETEXT[136]) + report(name, contact, describetion).emailReport() + del name, contact, describetion + + def ClearLog(): + global clearLog + clearLog = not clearLog + if clearLog: + tkinter.messagebox.showinfo(READABLETEXT[33], READABLETEXT[137]) + else: + tkinter.messagebox.showinfo(READABLETEXT[33], READABLETEXT[138]) + + print('生成部分及其余命令加载完成!') + + print('完成!') + + # 窗口部分 + print('增加窗口元素...') + global root + global __version__ + + root.title(READABLETEXT[41].format(__version__)) + root.geometry('900x900') # 像素 + try: + root.iconbitmap(bitmap='./resources/musicreater.ico', default='./resources/musicreater.ico') + except: + pass + + print('完成!') + + print('加载点击与页面更新命令...') + + # 音轨菜单被点击 + + def MusicList_selected(event): + global NowMusic + NowMusic = ListMusicList.get(ListMusicList.curselection()) + log('刷新音轨' + str(NowMusic)) + RefreshMusic(NowMusic) + print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) + + # 音符菜单被点击 + def NoteList_selected(event): + print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) + pass # 编辑音符操作 + + def CMDList_selected(event): + print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) + pass # 命令编辑操作 + + CMDList_selected("") # 保证函数使用 + # !!!!!上面这行在写完这个函数之后记得删!!!! + + print('菜单点击命令加载完成!') + + # 刷新音轨部分 + def RefreshMusic(Music=0): + LabelEntityName['text'] = READABLETEXT[42].format(dataset[0]['musics'][Music]['set']['EntityName']) + LabelScoreboardName['text'] = READABLETEXT[43].format(dataset[0]['musics'][Music]['set']['ScoreboardName']) + LabelInstrument['text'] = READABLETEXT[44].format(dataset[0]['musics'][Music]['set']['Instrument']) + LabelFileName['text'] = READABLETEXT[45].format(dataset[0]['musics'][Music]['set']['FileName']) + NoteList_var.set(()) # 为列表框设置新值 + for i in dataset[0]['musics'][Music]['notes']: + ListNoteList.insert(tk.END, str(i)) + + # 刷新主要部分 + def RefreshMain(): + LabelPackName['text'] = READABLETEXT[46].format(str(dataset[0]['mainset']['PackName'])) + # print(LabelPackName) + LabelMusicTitle['text'] = READABLETEXT[47].format(str(dataset[0]['mainset']['MusicTitle'])) + LabelIsRepeat['text'] = READABLETEXT[48].format(str(dataset[0]['mainset']['IsRepeat'])) + LabelPlayerSelect['text'] = READABLETEXT[49].format(str(dataset[0]['mainset']['PlayerSelect'])) + MusicList_var.set(()) # 为列表框设置新值 + for i in range(len(dataset[0]['musics'])): + ListMusicList.insert(tk.END, i) + global NowMusic + NowMusic = 0 + + def RefreshCMDList(CMDList): + ListCMDList.delete(tk.END) + for i in CMDList: + ListCMDList.insert(tk.END, str(i)) + + print('页面刷新函数加载完成!') + + def changePackName(event): + a = tkinter.simpledialog.askstring(title=READABLETEXT[50], prompt=READABLETEXT[139], initialvalue='Ryoun') + if a is None: + return + dataset[0]['mainset']['PackName'] = a + del a + RefreshMain() + print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) + + def changeMusicTitle(event): + a = tkinter.simpledialog.askstring(title=READABLETEXT[50], prompt=READABLETEXT[140], initialvalue='Noname') + if a is None: + return + dataset[0]['mainset']['MusicTitle'] = a + RefreshMain() + print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) + + def changeIsRepeat(event): + dataset[0]['mainset']['IsRepeat'] = not dataset[0]['mainset']['IsRepeat'] + RefreshMain() + print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) + + def changePlayerSelect(event): + dataset[0]['mainset']['PlayerSelect'] = tkinter.simpledialog.askstring(title=READABLETEXT[50], + prompt=READABLETEXT[141], + initialvalue='') + if dataset[0]['mainset']['PlayerSelect'] is None: + dataset[0]['mainset']['PlayerSelect'] = '' + RefreshMain() + print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) + + def changeEntityName(event): + global NowMusic + a = tkinter.simpledialog.askstring(title=READABLETEXT[51], prompt=READABLETEXT[142], + initialvalue='musicSupport') + if a is None: + return + dataset[0]['musics'][NowMusic]['set']['EntityName'] = a + RefreshMusic(NowMusic) + print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) + + def changeScoreboardName(event): + global NowMusic + a = tkinter.simpledialog.askstring(title=READABLETEXT[51], prompt=READABLETEXT[143], + initialvalue='musicSupport') + if a is None: + return + dataset[0]['musics'][NowMusic]['set']['ScoreboardName'] = a + RefreshMusic(NowMusic) + print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) + + def changeInstrument(event): + from nmcsup.const import Instuments as inst + global NowMusic + while True: # 改正:(True) + instemp = tkinter.simpledialog.askstring(title=READABLETEXT[51], prompt=READABLETEXT[144], + initialvalue='note.harp') + if instemp not in inst.keys(): # 改正:not instemp in inst.keys() ,not in 为固定写法 + if tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[145]): + dataset[0]['musics'][NowMusic]['set']['Instrument'] = instemp + del instemp + break + else: + smsg = READABLETEXT[52] + for i, j in inst.items(): + smsg += i + ' : ' + j + '\n' + tkinter.messagebox.showinfo(title=READABLETEXT[1], message=smsg) + del smsg + else: + dataset[0]['musics'][NowMusic]['set']['Instrument'] = instemp + del instemp + break + RefreshMusic(NowMusic) + print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) + + def changeFileName(event): + global NowMusic + a = tkinter.simpledialog.askstring(title=READABLETEXT[51], prompt=READABLETEXT[146], initialvalue='Music') + if a is None: + return + dataset[0]['musics'][NowMusic]['set']['FileName'] = a + RefreshMusic(NowMusic) + print(event) # 保证变量使用(虽然我不清楚金羿这为啥不调用要写个event) + # 滚滚滚,这个函数不能无参! ——金羿 + + print('标签点击命令加载完成!') + + def ResetSetting(): + global dataset + dataset[0]['mainset'] = {'PackName': 'Ryoun', 'MusicTitle': 'Noname', 'IsRepeat': False, 'PlayerSelect': ''} + RefreshMain() + + def DelNowMusic(): + global NowMusic + del dataset[0]['musics'][NowMusic] + NowMusic -= 1 + RefreshMain() + RefreshMusic(NowMusic) + + from nmcsup.vers import resetver + + print('按钮点击命令加载完成!') + print('完成!') + print('加载菜单与页面...') + + # 创建一个菜单 + main_menu_bar = tk.Menu(root) + + # 创建文件菜单 + filemenu = tk.Menu(main_menu_bar, tearoff=0) + + filemenu.add_command(label=READABLETEXT[53], command=openProject) + filemenu.add_command(label=READABLETEXT[54], command=openOldProject) + filemenu.add_command(label=READABLETEXT[55], command=SaveProject) + filemenu.add_command(label=READABLETEXT[56], command=SaveAsProject) + + filemenu.add_separator() # 分隔符 + + filemenu.add_command(label=READABLETEXT[57], command=exitapp) + + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=READABLETEXT[58], menu=filemenu) + + # 创建编辑菜单 + editmenu = tk.Menu(main_menu_bar, tearoff=0) + editmenu.add_command(label=READABLETEXT[59], command=FromMP3) + editmenu.add_command(label=READABLETEXT[60], command=FromListMidi) + editmenu.add_command(label=READABLETEXT[61], command=FromForm) + editmenu.add_command(label=READABLETEXT[62], command=FromText) + editmenu.add_separator() + editmenu.add_command(label=READABLETEXT[160], command=FromClassMidi) + editmenu.add_command(label=READABLETEXT[148], command=FromNewMidi) + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=READABLETEXT[63], menu=editmenu) + + # 创建函数菜单 + funcmenu = tk.Menu(main_menu_bar, tearoff=0) + funcmenu.add_command(label=READABLETEXT[64], command=MakeCMD) + funcmenu.add_command(label=READABLETEXT[65], command=MakeCMDdir) + funcmenu.add_command(label=READABLETEXT[66], command=MakePackFile) + funcmenu.add_separator() + funcmenu.add_command(label=READABLETEXT[147], command=MakeNewCMD) + funcmenu.add_command(label=READABLETEXT[153], command=MakeNewCMDdir) + funcmenu.add_command(label=READABLETEXT[154], command=MakeNewFunctionPackFile) + funcmenu.add_command(label=READABLETEXT[155], command=MakeNewFunctionPack_ResourcesPacks_File) + funcmenu.add_separator() + funcmenu.add_command(label=READABLETEXT[164], command=MakeClassCMD) + funcmenu.add_command(label=READABLETEXT[165], command=MakeClassCMDdir) + funcmenu.add_command(label=READABLETEXT[166], command=MakeClassFunctionPackFile) + + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=READABLETEXT[67], menu=funcmenu) + + # 创建世界菜单 + worldmenu = tk.Menu(main_menu_bar, tearoff=0) + worldmenu.add_command(label=READABLETEXT[68], command=ToBlockWorldEpt) + worldmenu.add_command(label=READABLETEXT[69], command=ToBlockWorld) + worldmenu.add_separator() + worldmenu.add_command(label=READABLETEXT[70], command=ToCmdWorldEpt) + worldmenu.add_command(label=READABLETEXT[71], command=ToCmdWorld) + worldmenu.add_separator() + worldmenu.add_command(label=READABLETEXT[72], command=toRSworldEPT) + worldmenu.add_command(label=READABLETEXT[73], command=toRSworld) + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=READABLETEXT[74], menu=worldmenu) + + # 创建结构功能菜单 + structureMenu = tk.Menu(main_menu_bar, tearoff=0) + structureMenu.add_command(label=READABLETEXT[92], command=toBDXfile) + structureMenu.add_command(label=READABLETEXT[76], command=toScbBDXfile) + structureMenu.add_command(label=READABLETEXT[77], command=world2BDX) + structureMenu.add_separator() + structureMenu.add_command(label=READABLETEXT[78], command=world2RyStruct) + + main_menu_bar.add_cascade(label=READABLETEXT[95], menu=structureMenu) + + # 创建辅助功能菜单 + otherMenu = tk.Menu(main_menu_bar, tearoff=0) + otherMenu.add_command(label=READABLETEXT[75], command=MakeFuncPlayer) + otherMenu.add_separator() + otherMenu.add_command(label=READABLETEXT[79], command=func2World) + otherMenu.add_command(label=READABLETEXT[80], command=bigFunc2World) + + main_menu_bar.add_cascade(label=READABLETEXT[81], menu=otherMenu) + + # 创建实验功能菜单 + trymenu = tk.Menu(main_menu_bar, tearoff=0) + trymenu.add_command(label=READABLETEXT[82], command=ShowCMD) + trymenu.add_command(label=READABLETEXT[83], command=wsPlay) + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=READABLETEXT[84], menu=trymenu) + + # 创建帮助菜单 + helpmenu = tk.Menu(main_menu_bar, tearoff=0) + helpmenu.add_command(label=READABLETEXT[85], command=ClearLog) + helpmenu.add_command(label=READABLETEXT[86], command=resetver) + helpmenu.add_command(label=READABLETEXT[152], command=end) + helpmenu.add_command(label=READABLETEXT[156], command=changeResourcesPath) + + helpmenu.add_separator() # 分隔符 + + helpmenu.add_command(label=READABLETEXT[87], command=apphelp) + helpmenu.add_command(label=READABLETEXT[88], command=appabout) + helpmenu.add_command(label=READABLETEXT[89], command=sendBugReport) + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=READABLETEXT[90], menu=helpmenu) + + # 窗口内容 + + # 上半部分框 + UpFrame = tk.Frame(root) + + # 左边的框(音乐总设置) + UpLeftFrame = tk.Frame(UpFrame, bg='white') + # 大标题 + tk.Label(UpLeftFrame, text=READABLETEXT[91], font=('', 20)).pack() + # 按钮式文本 + LabelPackName = tk.Label(UpLeftFrame, bg='white', + text=READABLETEXT[46].format(str(dataset[0]['mainset']['PackName'])), font=('', 15)) + LabelMusicTitle = tk.Label(UpLeftFrame, bg='white', + text=READABLETEXT[47].format(str(dataset[0]['mainset']['MusicTitle'])), font=('', 15)) + LabelIsRepeat = tk.Label(UpLeftFrame, bg='white', + text=READABLETEXT[48].format(str(dataset[0]['mainset']['IsRepeat'])), font=('', 15)) + LabelPlayerSelect = tk.Label(UpLeftFrame, bg='white', + text=READABLETEXT[49].format(str(dataset[0]['mainset']['PlayerSelect'])), + font=('', 15)) + # 绑定按钮 + LabelPackName.bind('', changePackName) + LabelMusicTitle.bind('', changeMusicTitle) + LabelIsRepeat.bind('', changeIsRepeat) + LabelPlayerSelect.bind('', changePlayerSelect) + # 装入容器 + LabelPackName.pack() + LabelMusicTitle.pack() + LabelIsRepeat.pack() + LabelPlayerSelect.pack() + # 按钮:重置项目设置 + tk.Button(UpLeftFrame, text=READABLETEXT[96], command=ResetSetting).pack() + # 装入窗口 + UpLeftFrame.pack(side='left') + + # 中间的框容器 + UpMidleFrame = tk.Frame(UpFrame, bg='blue') + # 列表 + MusicList_var = tk.StringVar() + ListMusicList = tk.Listbox(UpMidleFrame, listvariable=MusicList_var) + ListMusicList.bind('', MusicList_selected) # 设置选中响应函数 + ListMusicList.pack(side='left') + # 滑块 + tk.Scrollbar(UpMidleFrame, command=ListMusicList.yview).pack(side='left', fill='y') + # 装入窗口 + UpMidleFrame.pack(side='left') + + # 右边的框容器 + UpRightFrame = tk.Frame(UpFrame, bg='white') + # 大标题 + tk.Label(UpRightFrame, text=READABLETEXT[97], font=('', 20)).pack() + # 按钮式文本 + LabelEntityName = tk.Label(UpRightFrame, bg='white', + text=READABLETEXT[42].format(dataset[0]['musics'][NowMusic]['set']['EntityName']), + font=('', 15)) + LabelScoreboardName = tk.Label(UpRightFrame, bg='white', text=READABLETEXT[43].format( + dataset[0]['musics'][NowMusic]['set']['ScoreboardName']), font=('', 15)) + LabelInstrument = tk.Label(UpRightFrame, bg='white', + text=READABLETEXT[44].format(dataset[0]['musics'][NowMusic]['set']['Instrument']), + font=('', 15)) + LabelFileName = tk.Label(UpRightFrame, bg='white', + text=READABLETEXT[45].format(dataset[0]['musics'][NowMusic]['set']['FileName']), + font=('', 15)) + # 绑定按钮 + LabelEntityName.bind('', changeEntityName) + LabelScoreboardName.bind('', changeScoreboardName) + LabelInstrument.bind('', changeInstrument) + LabelFileName.bind('', changeFileName) + # 装入框容器 + LabelEntityName.pack() + LabelScoreboardName.pack() + LabelInstrument.pack() + LabelFileName.pack() + # 按钮:删除选中音轨 + tk.Button(UpRightFrame, text=READABLETEXT[102], command=DelNowMusic).pack() + # 装入窗口 + UpRightFrame.pack(side='left') + + # 上半部分框容器装入窗口 + UpFrame.pack() + + # 下半部分框容器 + DownFrame = tk.Frame(root, bg='blue') + + # 经典名言语录 + import datetime + + if datetime.date.today().month == 4 and datetime.date.today().day == 3: + tk.Label(DownFrame, text='金羿生日快乐!!',fg='yellow', bg='red', font=('DengXian', 20, 'bold')).pack(fill='x') + else: + import random + texts = open('./resources/myWords.txt', 'r', encoding='utf-8').readlines() + tk.Label(DownFrame, text=texts[random.randint(0, len(texts) - 1)].replace('\n', '').replace('\\n', '\n'), + fg='white', bg='black', font=('DengXian Light', 20)).pack(fill='x') + del texts + + # 音符列表菜单 + NoteList_var = tk.StringVar() + ListNoteList = tk.Listbox(DownFrame, listvariable=NoteList_var, width=40, height=30) + ListNoteList.bind('', NoteList_selected) # 设置选中响应函数 + ListNoteList.pack(side='left') + # 音符列表滑块 + tk.Scrollbar(DownFrame, command=ListNoteList.yview).pack(side='left', fill='y') + + # 指令列表菜单 + ListCMDList = tk.Text(DownFrame, height=37, width=40) + ListCMDList.pack(side='left') + # 指令列表滑块 + tk.Scrollbar(DownFrame, command=ListCMDList.yview).pack(fill='y', side='left') + + # 下半部分容器载入窗口 + DownFrame.pack() + + RefreshMain() + + # 将菜单添加到主窗口中 + root.config(menu=main_menu_bar) + + print('完成!') + + log('启动root.mainloop(窗口)') + + if len(sys.argv) != 1: + log('初始化打开音·创项目' + sys.argv[1]) + global is_save + is_save = True + error = True + try: + with open(sys.argv[1], 'r', encoding='UTF-8') as c: + dataset[0] = json.load(c) + error = False + except OSError: + print(READABLETEXT[8].format(sys.argv[1])) + log('无法打开' + sys.argv[1]) + return + finally: + if error is True: + print(READABLETEXT[8].format(sys.argv[1])) + log('无法打开' + sys.argv[1]) + return + global is_new_file + global ProjectName + is_new_file = False + ProjectName = sys.argv[1] + RefreshMain() + RefreshMusic(NowMusic) + + # 进入窗口消息循环 + root.mainloop() + log('退出') + del filemenu, editmenu, helpmenu, otherMenu + + exitapp() + + +if __name__ == '__main__': + __main__() + +################## + + # def openNewProject(): + # global is_save + # if is_save is not True: + # result = tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[106]) + # if result: + # SaveProject() + # fn = tkinter.filedialog.askopenfilename(title=READABLETEXT[7], initialdir=r'./', + # filetypes=[(READABLETEXT[108], '.msct'), (READABLETEXT[112], '*')], + # multiple=True) + # if fn is None or fn == '': + # return + # else: + # # print(fn) + # fn = fn[0] + # # print(fn) + # log("尝试打开:" + fn) + # try: + # try: + # with open(fn, 'rb') as C: + # global dataset + # # print(pickle.load(C)) + # read = pickle.load(C) # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # # print(read) + # dataset = read[0] + # pkl1 = read[1] + # log("读取新文件成功") + # with open("1.pkl", 'wb') as w: + # pickle.dump(pkl1, w) + # except KeyError: + # with open(fn, 'rb') as C: + # dataset[0] = pickle.load(C) + # log("读取新文件成功") + # except pickle.UnpicklingError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,测试后改为: + # # pickle.UnpicklingError + # print(READABLETEXT[8].format(fn)) + # log('无法打开{}'.format(fn)) + # return + # global is_new_file + # global ProjectName + # is_new_file = False + # ProjectName = fn + # del fn + # global NowMusic + # RefreshMain() + # RefreshMusic(NowMusic) + + # def openClassProject(): + # global is_save + # if is_save is not True: + # result = tkinter.messagebox.askyesno(title=READABLETEXT[1], message=READABLETEXT[106]) + # if result: + # SaveProject() + # fn = tkinter.filedialog.askopenfilename(title=READABLETEXT[7], initialdir=r'./', + # filetypes=[(READABLETEXT[108], '.msct'), (READABLETEXT[112], '*')], + # multiple=True) + # if fn is None or fn == '': + # return + # else: + # # print(fn) + # fn = fn[0] + # # print(fn) + # log("尝试打开:" + fn) + # try: + # try: + # with open(fn, 'rb') as C: + # global dataset + # # print(pickle.load(C)) + # read = pickle.load(C) # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # # 重要的事情说三遍!!!pickle.load只能load一次,所以多load几次就有bug,要一次读完! + # # print(read) + # dataset = read + # log("读取新文件成功") + # except KeyError: + # with open(fn, 'rb') as C: + # dataset[0] = pickle.load(C) + # log("读取新文件成功") + # except pickle.UnpicklingError: # 程序规范修改:根据新的语法标准:except后面不能没有错误类型,测试后改为: + # # pickle.UnpicklingError + # print(READABLETEXT[8].format(fn)) + # log('无法打开{}'.format(fn)) + # return + # global is_new_file + # global ProjectName + # is_new_file = False + # ProjectName = fn + # del fn + # global NowMusic + # RefreshMain() + # RefreshMusic(NowMusic) + + +# ------------------ + # filemenu.add_separator() + # + # filemenu.add_command(label=READABLETEXT[149], command=openNewProject) + # filemenu.add_command(label=READABLETEXT[150], command=SaveNewProject) + # filemenu.add_command(label=READABLETEXT[151], command=SaveAsNewProject) + + # filemenu.add_separator() + # + # filemenu.add_command(label=READABLETEXT[161], command=openClassProject) + # filemenu.add_command(label=READABLETEXT[162], command=SaveClassProject) + # filemenu.add_command(label=READABLETEXT[163], command=SaveAsClassProject) diff --git a/README.md b/README.md index 32c853a..f0065dc 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,58 @@ -# 音·创 Musicreater +

音·创 Musicreater

-### 介绍 -音·创 Musicreater 是由金羿(*W-YI*)开发的一款 **《我的世界:基岩版》** 音乐生成辅助软件 +

+ +

-欢迎加群:861684859 +

+ +

-### 作者 +[![][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) -金羿 (Eilles):主要作者,开发了音·创主体,及其前身“函数音乐生成器”、“世界音创”。 +简体中文🇨🇳 | [English🇬🇧](README_EN.md) -bgArray “诸葛亮与八卦阵”:修复bug,改进代码美观度,增加新功能,更改数据格式等。 +## 软件介绍🚀 -### 软件架构 +音·创 Musicreater 是一款免费开源的 **《我的世界:基岩版》** 音乐制作软件 -软件采用 *Python* 作为第一语言,目前还没有使用其他语言辅助。使用 *Tkinter* 为图形库。 +欢迎加群:[861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr) -支持 Windows7+ 以及各个支持 Python3.8 的 Linux +**注意注意注意!!!本程序尚在测试与开发阶段,且代码重构未完成,请自行定夺使用。** -***各位开发人员注意!!!多语言支持请使用`READABLETEXT`常量输出文字!!!如需补充,请在简体中文的语言文件(zhCN.py)中补充!!!*** +## 软件作者✒ +金羿 Eilles:我的世界基岩版指令师,个人开发者,B站不知名UP主,南昌在校高中生。 + +诸葛亮与八卦阵 bgArray:我的世界基岩版玩家,喜欢编程和音乐,深圳初一学生。 + +## 软件架构🏢 + +软件采用 *Python* 作为第一语言,目前还没有使用其他语言辅助。使用可更换的UI结构库,即开发人员可以通过更换display.py文件随心所欲地切换UI库;后期将支持插件自加载。 + +支持 Windows7+ 以及各个支持 Python3.6+ 的 Linux + +***各位开发人员注意!!!多语言支持请使用函数`_`加载文字!!!如需补充,请在简体中文的语言文件(zh-CN.lang)中补充!!!*** + +## 使用教程📕 ### 安装教程 -正在到来。 +下载[音·创自动安装器](https://gitee.com/EillesWan/Musicreater/releases/v0.2.0.0-Delta),将其放在你希望安装音·创的位置,运行后将自动安装。 + +提示:下载源最好选择\"2 GitHub\"。 ### 从源代码运行教程 #### Windows7+ -0. [Gitee下载(需要登陆)](https://gitee.com/EillesWan/Musicreater/repository/archive/master.zip) - [Github下载(慢)](https://github.com/EillesWan/Musicreater/archive/refs/heads/master.zip)本程序源代码 +0. [Gitee下载(需要登陆)](https://gitee.com/EillesWan/Musicreater) + [Github下载(慢)](https://github.com/EillesWan/Musicreater)本程序源代码 1. 安装Python 3.8.10 [下载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) @@ -57,15 +80,13 @@ python3 补全库.py python3 Musicreater.py ``` - ### 使用说明 1. 直接运行就好 -2. 看得懂简体中文字的不一定全会用 -3. 最好要懂一点点英文 +2. 后期会出详细的使用教程 +3. 如果在使用过程中发现了bug拜托请上报给我,详见下方联系方式 - -### 诸葛亮与八卦阵的说明(不必要) +## 诸葛亮与八卦阵的关于羽音缭绕资源包应用地说明(不必要)📖 1. 首先!这里的提示是给想使用多音色资源包的人的,如果你想用就请下载 [神羽资源包(神羽自己的链接)](https://pan.baidu.com/s/11uoq5zwN7c3rX-98DqVpJg)提取码:ek3t 2. 下载到你自己电脑上某个位置,可以不放置于本项目下。音色资源包较大,可以选取只下载: @@ -82,7 +103,7 @@ python3 Musicreater.py 6. 如果你想使用音色资源包来制作函数,那么解析时你应该用 *音创*->编辑->从midi导入音轨且用新方法解析, 然后再使用 *音创*->函数(包)->下面的四个新函数 -### 致谢 +## 致谢🙏 1. 感谢由 [Fuckcraft](https://github.com/fuckcraft) “鸣凤鸽子”等 带来的我的世界websocket服务器功能 2. 感谢 昀梦\ 找出指令生成错误bug并指正 @@ -93,8 +114,9 @@ python3 Musicreater.py 7. 感谢广大群友为此程序提供的测试等支持 8. 若您对我们有所贡献但您的名字没有显示在此列表中,请联系我! +## 联系我们📞 -### 作者\<*金羿*\>(W-YI)联系方式 +### 作者\<*金羿*\>(Eilles)联系方式 1. QQ 2647547478 2. 电邮 EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com @@ -102,4 +124,38 @@ python3 Musicreater.py ### 作者\<*诸葛亮与八卦阵*\>(bgArray) 联系方式 -1. QQ 4740437765 \ No newline at end of file +1. QQ 4740437765 + +## 待办事项 + +* - [x] 可以使用由神羽提供的音乐资源包 +* - [x] 支持多语言 +* - [x] 支持创建可被Fastbuilder导入的.BDX文件支持 +* - [ ] 1.可以导出自定义的结构文件用于存储要导入地图中的结构 +* - [ ] 2.进度条 +* - [ ] 3.可以将音乐写入音符盒(红乐) +* - [ ] 4.修改UI界面使之适应当前功能 +* - [ ] 5.支持自动给音符盒绑定更多的音色 +* - [ ] 6.可以由.schematic文件导入地图,亦可反向处理 +* - [x] 7.制作软件下载器使用户更直观地操作 +* - [x] 8.支持自定义创建websockeet服务器播放音乐 +* - [ ] 9.支持使用红石播放音乐 +* - [ ] 10.支持采用延时的播放器 +* - [ ] 11.支持使用bdx导出结构 +* - [ ] 12.支持采用tp的方法播放 +* - [ ] 13.支持识别曲谱(简谱)图片解析音乐 +* - [ ] 14.支持使用瀑布流的方式播放音乐 +* - [ ] 15.支持读入Everyone Piano的曲谱文件(.eop) +* - [ ] 16.支持读入Musescore的通用曲谱文件,即musicXML(.mscz、.mscx) +* - [ ] 17.支持自动搜寻地图目录位置(网易&微软) +* - [ ] 18.支持读入JPword曲谱文件(.jpd) +* - [ ] 19.新的UI设计,以及UI主题文件 +* - [ ] 20.以小节为单位做音符播放时间对标 + + +[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 diff --git a/README_en.md b/README_EN.md similarity index 57% rename from README_en.md rename to README_EN.md index af1de93..a6c82a3 100644 --- a/README_en.md +++ b/README_EN.md @@ -1,32 +1,57 @@ -# Musicreater +

音·创 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 +

+ +

-###Author +[![][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) -Eilles (金羿):The main author, who developed the most and especially the principal parts of Musicreater, and its predecessors, which has been called as "*Minecraft Function Music Maker*", "*Note Fun Creater*", "*Note World Creater*"(now ,they are united as ***Musicreater***!) +[简体中文🇨🇳](README.md) | English🇬🇧 + +**Notice that the language support of *README* may be a little SLOW.** + +## Introduction🚀 + +Musicreater(音·创) is an free open source software which is used for making and also creating music in **Minecraft: Bedrock Edition**. + +Welcome to join our QQ group: [861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr) + +**ATTENTION!** This software is under testing and developing, there is still a lot of bugs needed to be fixed. Please use it wisely. + +### 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. -### Framework +### Framework🏢 -Using *Python* to develop, using Tkinter as a graphics library. +Developed under *Python3.8 3.9*. However, theoretically support Python3.6+. -Support Windows7+ && Linux (that supports Python3.8) +Support Windows7+ && Linux (that supports Python3.6+) -***ATTENTION TO DEVELOPERS!!! TO SUPPORT DIFFERENT LANGUAGES, PLEASE USE CONSTANT `READABLETEXT` TO OUTPUT!!! IF YOU NEED TO SUPPLEMENT, PLEASE ADD THEM IN SIMPLEFIED CHINESE\'S LANGUAGE FILE(zhCN.py), WHEATHER WHAT LANGUAGE YOU USE!!!*** +***ATTENTION TO DEVELOPERS!!! TO SUPPORT DIFFERENT LANGUAGES, PLEASE USE FUNCTION(METHOD) `_` TO LOAD TEXTs!!! IF YOU NEED TO SUPPLEMENT, PLEASE ADD THEM IN SIMPLEFIED CHINESE\'S LANGUAGE FILE(zh-CN.lang), WHEATHER WHAT LANGUAGE YOU USE!!!*** +## Instructions📕 ### Installation -Comming soon... +Download the *[MSCT Auto Installer](https://github.com/EillesWan/Musicreater/releases/tag/v0.2.0.0-Delta)*, put it in a directory that you want to install *Musicreater* into. Then run the auto installer and it will help you to install the *Musicreator* as well as Python3.8(if you haven\'t install it) + +Tips: You'd better choose the \"2 GitHub\" download source ### Run with Source Code -#### Windows +#### Windows7+ 0. First, download the source code pack of Musicreater. [Download from Gitee (Need to Login)](https://gitee.com/EillesWan/Musicreater/repository/archive/master.zip) @@ -58,15 +83,13 @@ python3 补全库.py python3 Musicreater.py ``` +### Instructions of Using -### Instructions +1. Just run Musicreater.pyc(or .py) if you have installed well +2. Detailed instructions is coming soon +3. If you find a bug, could you please report it to me? My contact info is right below. -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. - - -### Explanation of bgArray 诸葛亮与八卦阵 (unnecessary) +## Explanation of the use of *PlumeAudioSurrounding Resource Pack* by bgArray (unnecessary)📖 1. First! The tips here are for those who want to use the multi tone resource package, [Shenyu resource package (Shenyu's own link)](https://pan.baidu.com/s/11uoq5zwN7c3rX-98DqVpJg) \(Extraction code: `ek3t`\) 2. Download it to any location on your PC. Note that it does ***not*** need to be placed in the directory where *Musicreater* are. The audio resource package is large, so you can choose to download only:`神羽资源包_乐器、音源的资源包\羽音缭绕-midiout_25.0`. @@ -81,7 +104,7 @@ python3 Musicreater.py 6. If you want to use the Miracle Plume Bedrock Edition Audio Resource Pack to make .mcfunction s, you should use Musicreater -> Edit - > Import audio tracks from MIDI and parse them with a new method, and then use it Musicreater - > function (package) - > the following four new functions -### Thanks +## Thanks🙏 1. Thank [Fuckcraft](https://github.com/fuckcraft) *(“鸣凤鸽子” ,etc)* for the function of Creating the Websocket Server for Minecraft: Bedrock Edition. - *!! They have given me the rights to directly copy the lib into Musicreater* @@ -89,17 +112,29 @@ Musicreater - > function (package) - > the following four new functions 3. Thank *Charlie_Ping “查理平”* for bdx convert funtion. 4. Thank *CMA_2401PT* for BDXWorkShop as the .bdx structure's operation guide. 5. Thank *Miracle Plume “神羽”* \ for the Miracle Plume Bedrock Edition Audio Resource Pack -6. Thank *Arthur Morgan* for his/her biggest support for Musicreater +6. Thank *Arthur Morgan* for his/her biggest support for the debugging of Musicreater 7. Thanks for a lot of groupmates who support me and help me to test the program. 8. If you have give me some help but u haven't been in the list, please contact me. +## Contact Information📞 -### Contact *Eilles(W-YI)*(金羿) +### Author *Eilles*(金羿) 1. QQ 2647547478 2. E-mail EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com 3. WeChat WYI_DoctorYI -### Contact *bgArray*(诸葛亮与八卦阵) +### Author *bgArray*(诸葛亮与八卦阵) -1. QQ 4740437765 \ No newline at end of file +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 \ No newline at end of file diff --git a/bgArrayLib/__pycache__/bpm.cpython-38.pyc b/bgArrayLib/__pycache__/bpm.cpython-38.pyc index 672e09b..a0ea2eb 100644 Binary files a/bgArrayLib/__pycache__/bpm.cpython-38.pyc and b/bgArrayLib/__pycache__/bpm.cpython-38.pyc differ diff --git a/bgArrayLib/bpm.py b/bgArrayLib/bpm.py index 6e1f3f4..b6fdc30 100644 --- a/bgArrayLib/bpm.py +++ b/bgArrayLib/bpm.py @@ -1,12 +1,22 @@ import mido import numpy +''' +bpm +bites per minutes +每分钟的拍数 +''' def mt2gt(mt, tpb_a, bpm_a): return round(mt / tpb_a / bpm_a * 60) -def get(mid:mido.MidiFile): +def get(mid:mido.MidiFile) -> int: + '''传入一个 MidiFile, 返回其音乐的bpm + :param mid : mido.MidFile + mido库识别的midi文件数据 + :return bpm : int + ''' # mid = mido.MidiFile(mf) long = mid.length tpb = mid.ticks_per_beat diff --git a/fcwslib/版权声明.png b/fcwslib/版权声明.png new file mode 100644 index 0000000..05ebcf5 Binary files /dev/null and b/fcwslib/版权声明.png differ diff --git a/languages/__pycache__/__init__.cpython-37.pyc b/languages/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..3affb8f Binary files /dev/null and b/languages/__pycache__/__init__.cpython-37.pyc differ diff --git a/languages/__pycache__/__init__.cpython-39.pyc b/languages/__pycache__/__init__.cpython-39.pyc index 8b056f0..eb9b629 100644 Binary files a/languages/__pycache__/__init__.cpython-39.pyc and b/languages/__pycache__/__init__.cpython-39.pyc differ diff --git a/languages/__pycache__/lang.cpython-37.pyc b/languages/__pycache__/lang.cpython-37.pyc new file mode 100644 index 0000000..8c90446 Binary files /dev/null and b/languages/__pycache__/lang.cpython-37.pyc differ diff --git a/languages/__pycache__/lang.cpython-38.pyc b/languages/__pycache__/lang.cpython-38.pyc index 1b4ae6b..f5aba45 100644 Binary files a/languages/__pycache__/lang.cpython-38.pyc and b/languages/__pycache__/lang.cpython-38.pyc differ diff --git a/languages/__pycache__/zhCN.cpython-37.pyc b/languages/__pycache__/zhCN.cpython-37.pyc new file mode 100644 index 0000000..2612ad5 Binary files /dev/null and b/languages/__pycache__/zhCN.cpython-37.pyc differ diff --git a/languages/__pycache__/zhCN.cpython-39.pyc b/languages/__pycache__/zhCN.cpython-39.pyc index a545850..4da8852 100644 Binary files a/languages/__pycache__/zhCN.cpython-39.pyc and b/languages/__pycache__/zhCN.cpython-39.pyc differ diff --git a/languages/autosave.tmp.txt b/languages/autosave.tmp.txt new file mode 100644 index 0000000..874d3f8 --- /dev/null +++ b/languages/autosave.tmp.txt @@ -0,0 +1,13 @@ +zh-ME +喵喵文 中国大陆 +Meow Catsese, China Mainland +喵喵喵~ 祖国喵~ +金羿,Email EillesWan@outlook.com,QQ 2647547478 +音创创喵~ +音·创 Musicreater +音创创喵的主人们 +凌天之云创新我的世界开发团队\n×\n凌天之云创新计算机应用软件开发团队 +~ 主人们 ~ +~ 爸爸妈妈们 ~ +好哒~ + diff --git a/languages/const2string.py b/languages/const2string.py index e4d0b3e..53a2e5c 100644 --- a/languages/const2string.py +++ b/languages/const2string.py @@ -1,16 +1,19 @@ # -*- coding:utf-8 -*- +'''此功能已废弃''' + + # W-YI 金羿 # QQ 2647547478 # 音·创 开发交流群 861684859 # Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com -# 版权所有 Team-Ryoun 金羿 +# 版权所有 Team-Ryoun 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") # 若需转载或借鉴 请附作者 """ - Copyright 2022 Eilles Wan (金羿) + 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. diff --git a/languages/lang.py b/languages/lang.py index 8f92190..e78dd08 100644 --- a/languages/lang.py +++ b/languages/lang.py @@ -1,20 +1,206 @@ # -*- coding:utf-8 -*- +'''对于音·创的语言支持兼语言文件编辑器''' +""" + Copyright 2022 Team-Ryoun + + 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. +""" DEFAULTLANGUAGE = 'zh-CN' LANGUAGELIST = { + # 第一个是语言的中文名称和地区 + # 第二个是语言的英文名称和地区 + # 第三个是语言的本地名称和地区 'zh-CN': ( "简体中文 中国大陆", - "Simplified Chinese, China Mainland", + "Simplified Chinese - China Mainland", + "简体中文 中国大陆", ), + 'zh-TW': ( + "繁体中文 中国台湾省", + "Traditional Chinese - Taiwan, China", + "正體中文,中国台灣省", + ), + # 'zh-HK': ( + # "繁体中文 香港", + # "Traditional Chinese - the Hong Kong Special Administrative Region", + # "繁體中文,香港特別行政區", + # ), + # 'zh-MO': ( + # "繁体中文 澳门", + # "Traditional Chinese - the Macao Special Administrative Region", + # "繁體中文,澳門特別行政區", + # ), 'en-GB': ( - "英式英语 大不列颠", - "British English, Great Britain", + "英语 英国", + "British English - the United Kingdom", + "British English - the United Kingdom", ), + 'zh-ME' : ( + "喵喵文 中国大陆", + "Meow Catsese - China Mainland" + "喵喵喵~ 祖国喵~" + ) } -if DEFAULTLANGUAGE == 'zh-CN': +# 对于旧版本音·创的语言支持 +# 重构之后将停止使用 +try: from languages.zhCN import READABLETEXT -elif DEFAULTLANGUAGE == 'en-GB': - from languages.enGB import READABLETEXT +except: + pass + + +from msctLib.log import log + +def __loadLanguage(languageFilename: str): + with open(languageFilename, 'r', encoding='utf-8') as languageFile: + _text = {} + for line in languageFile: + if line.startswith('#'): + continue + line = line.split(' ', 1) + _text[line[0]] = line[1].replace('\n', '') + langkeys = _text.keys() + with open(languageFilename.replace(languageFilename[-10:-5], 'zh-CN'), 'r', encoding='utf-8') as defaultLangFile: + for line in defaultLangFile: + if line.startswith('#'): + continue + line = line.split(' ', 1) + if not line[0] in langkeys: + _text[line[0]] = line[1].replace('\n', '') + from msctLib.log import log + log(f'丢失对于 {line[0]} 的本地化文本', 'WARRING') + langkeys = _text.keys() + # print(_text) + return _text + + +if not DEFAULTLANGUAGE == 'zh-CN': + if DEFAULTLANGUAGE in LANGUAGELIST.keys(): + _TEXT = __loadLanguage('./languages/' + DEFAULTLANGUAGE + '.lang') + else: + raise KeyError(f'无法打开默认语言{DEFAULTLANGUAGE}') + + +def wordTranslate(singleWord: str, debug: bool = False): + import requests + try: + return \ + requests.post('https://fanyi.baidu.com/sug', data={'kw': f'{singleWord}'}).json()['data'][0]['v'].split( + '; ')[0] + except: + log(f"无法翻译文本{singleWord}", level='WARRING', isPrinted=debug) + return None + + +def _(text: str, debug: bool = False): + try: + return _TEXT[text] + except: + if debug: + raise KeyError(f'无法找到翻译文本{text}') + else: + log(f'无法找到本地化文本{text}','ERROR') + return '' + + +if __name__ == '__main__': + # 启动语言编辑器 + import tkinter as tk + from tkinter.filedialog import askopenfilename as askfilen + + LANGNAME = _('LANGLOCALNAME') + + + def _changeDefaultLang(): + global _TEXT + global DEFAULTLANGUAGE + + fileName = askfilen(title='选择所翻译的语言文件', initialdir=r'./', + filetypes=[('音·创语言文件', '.lang'), ('所有文件', '*')], + defaultextension='.lang', + initialfile='.lang') + _TEXT = __loadLanguage(fileName) + DEFAULTLANGUAGE = _('LANGKEY') + LANGNAME = _('LANGLOCALNAME') + + orignText = '' + transText = '' + for i, j in _TEXT.items(): + orignText += i + '\n' + transText += j + '\n' + + Origntextbar.insert('end', orignText) + Translatetextbar.insert('end', transText) + + global setlangbutton + setlangbutton['text'] = f'对标语言{LANGNAME}' + + + def _autoSave(event=None): + with open('autosave.tmp.txt', 'w', encoding='utf-8') as f: + f.write(Translatetextbar.get(1.0, 'end')) + print(str(event)) + + + root = tk.Tk() + + root.geometry('600x500') + + root.bind("", _autoSave) + + nowText = '' + + Orignrame = tk.Frame(root, bd=2) + Translaterame = tk.Frame(root, bd=2) + + Orignscrollbar = tk.Scrollbar(Orignrame) + Origntextbar = tk.Text(Orignrame, width=35, height=40) + + Translatetextbar = tk.Text(Translaterame, width=40, height=37, undo=True) + Translatescrollbar = tk.Scrollbar(Translaterame) + + def ctrlZ(): + Translatetextbar.edit_undo() + Translatetextbar.bind("", ctrlZ) + + def ctrlY(): + Translatetextbar.edit_redo() + Translatetextbar.bind("", ctrlY) + + Translatetextbar.bind("", _autoSave) + + tk.Button(Translaterame, text='保存', command=_autoSave).pack(side='bottom', fill='x') + + tk.Label(Orignrame, text='中文原文').pack(side='top') + Origntextbar.pack(side='left', fill='y') + Orignscrollbar.pack(side='left', fill='y') + + setlangbutton = tk.Button(Translaterame, text=f'对标语言{LANGNAME}', command=_changeDefaultLang) + setlangbutton.pack(side='top') + Translatescrollbar.pack(side='right', fill='y') + Translatetextbar.pack(side='right', fill='y') + + Orignscrollbar.config(command=Origntextbar.yview) + Origntextbar.config(yscrollcommand=Orignscrollbar.set) + + Translatescrollbar.config(command=Translatetextbar.yview) + Translatetextbar.config(yscrollcommand=Translatescrollbar.set) + + Orignrame.pack(side='left') + Translaterame.pack(side='right') + + tk.mainloop() diff --git a/languages/zh-CN.lang b/languages/zh-CN.lang new file mode 100644 index 0000000..1a260fb --- /dev/null +++ b/languages/zh-CN.lang @@ -0,0 +1,16 @@ +# 音·创 本地化语言文件 +# 使用 空格 把键与对应文本隔开 +# 使用 井字符 在每一行的开头编写注释 +# 注意!井字符请开头放,切勿含有空格 +# 也切勿在正文结尾放! +LANGKEY zh-CN +LANGCHINESENAME 简体中文 中国大陆 +LANGENGLIFHNAME Simplified Chinese, Chinese Mainland +LANGLOCALNAME 简体中文 中国大陆 +MSCT 音·创 +F音创 音·创 Musicreater +关于 音·创 - 关于 +凌云pairs 凌天之云创新我的世界开发团队\n×\n凌天之云创新计算机应用软件开发团队 +开发者 - 开发人员 - +译者 - 翻译人员 - +确定 确定 \ No newline at end of file diff --git a/languages/zh-ME.lang b/languages/zh-ME.lang new file mode 100644 index 0000000..614cb97 --- /dev/null +++ b/languages/zh-ME.lang @@ -0,0 +1,17 @@ +# 音创创喵的 本地化语言文件 +# 使用 空格 把键与对应文本隔开 +# 使用 井字符 在每一行的开头编写注释 +# 注意!井字符请开头放,切勿含有空格 +# 也切勿在正文结尾放! +LANGKEY zh-ME +LANGCHINESENAME 喵喵文 中国大陆 +LANGENGLIFHNAME Meow Catsese, China Mainland +LANGLOCALNAME 喵喵喵~ 祖国喵~ +TRANSLATERS 金羿,Email EillesWan@outlook.com,QQ 2647547478 +MSCT 音创创喵~ +F音创 音·创 Musicreater +关于 音创创喵的主人们 +凌云pairs 凌天之云创新我的世界开发团队\n×\n凌天之云创新计算机应用软件开发团队 +开发者 ~ 主人们 ~ +译者 ~ 爸爸妈妈们 ~ +确定 好哒~ diff --git a/msctLib/UI设计图.pdn b/msctLib/UI设计图.pdn new file mode 100644 index 0000000..6ff3a9c Binary files /dev/null and b/msctLib/UI设计图.pdn differ diff --git a/msctLib/UI设计图.png b/msctLib/UI设计图.png new file mode 100644 index 0000000..9ccf849 Binary files /dev/null and b/msctLib/UI设计图.png differ diff --git a/msctLib/__init__.py b/msctLib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/msctLib/__pycache__/__init__.cpython-37.pyc b/msctLib/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..a2a7a65 Binary files /dev/null and b/msctLib/__pycache__/__init__.cpython-37.pyc differ diff --git a/msctLib/__pycache__/__init__.cpython-38.pyc b/msctLib/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..81572fd Binary files /dev/null and b/msctLib/__pycache__/__init__.cpython-38.pyc differ diff --git a/msctLib/__pycache__/__init__.cpython-39.pyc b/msctLib/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000..033498f Binary files /dev/null and b/msctLib/__pycache__/__init__.cpython-39.pyc differ diff --git a/msctLib/__pycache__/data.cpython-38.pyc b/msctLib/__pycache__/data.cpython-38.pyc new file mode 100644 index 0000000..bc038db Binary files /dev/null and b/msctLib/__pycache__/data.cpython-38.pyc differ diff --git a/msctLib/__pycache__/display.cpython-38.pyc b/msctLib/__pycache__/display.cpython-38.pyc new file mode 100644 index 0000000..9fadcc9 Binary files /dev/null and b/msctLib/__pycache__/display.cpython-38.pyc differ diff --git a/msctLib/__pycache__/function.cpython-38.pyc b/msctLib/__pycache__/function.cpython-38.pyc new file mode 100644 index 0000000..2987cdb Binary files /dev/null and b/msctLib/__pycache__/function.cpython-38.pyc differ diff --git a/msctLib/__pycache__/log.cpython-37.pyc b/msctLib/__pycache__/log.cpython-37.pyc new file mode 100644 index 0000000..68fedbe Binary files /dev/null and b/msctLib/__pycache__/log.cpython-37.pyc differ diff --git a/msctLib/__pycache__/log.cpython-38.pyc b/msctLib/__pycache__/log.cpython-38.pyc new file mode 100644 index 0000000..a7e7571 Binary files /dev/null and b/msctLib/__pycache__/log.cpython-38.pyc differ diff --git a/msctLib/__pycache__/log.cpython-39.pyc b/msctLib/__pycache__/log.cpython-39.pyc new file mode 100644 index 0000000..26b6f31 Binary files /dev/null and b/msctLib/__pycache__/log.cpython-39.pyc differ diff --git a/msctLib/bugExecution.exe b/msctLib/bugExecution.exe new file mode 100644 index 0000000..99ba600 Binary files /dev/null and b/msctLib/bugExecution.exe differ diff --git a/msctLib/buildIN.py b/msctLib/buildIN.py new file mode 100644 index 0000000..3bcf8a8 --- /dev/null +++ b/msctLib/buildIN.py @@ -0,0 +1,50 @@ +# -*- coding: UTF-8 -*- +"""音·创的核心内置组件功能集合""" + + + +class version: + libraries = ( + 'mido', 'amulet', 'amulet-core', 'amulet-nbt', 'piano_transcription_inference', 'pypinyin', + 'pyinstaller', 'py7zr','websockets', 'torch', 'requests' + ) + """当前所需库""" + + version = ('0.2.0', 'Delta',) + """当前版本""" + + def __init__(self) -> None: + + self.libraries = version.libraries + """当前所需库""" + + self.version = version.version + """当前版本""" + + + def installLibraries(self,index:str = 'https://pypi.tuna.tsinghua.edu.cn/simple'): + """安装全部开发用库""" + from sys import platform + import os + if platform == 'win32': + import shutil + try: + shutil.rmtree(os.getenv('APPDATA') + '\\Musicreater\\') + except FileNotFoundError: + pass + for i in self.libraries: + print("安装库:" + i) + os.system(f"python -m pip install {i} -i {index}") + elif platform == 'linux': + os.system("sudo apt-get install python3-pip") + os.system("sudo apt-get install python3-tk") + os.system("sudo apt-get install python3-tkinter") + for i in self.libraries: + print("安装库:" + i) + os.system(f"sudo python3 -m pip install {i} -i {index}") + + + def __call__(self): + '''直接安装库,顺便返回一下当前版本''' + self.installLibraries() + return self.version diff --git a/msctLib/data.py b/msctLib/data.py new file mode 100644 index 0000000..f22cea4 --- /dev/null +++ b/msctLib/data.py @@ -0,0 +1,151 @@ +# -*- coding:utf-8 -*- + + +import pickle +import json +from typing import Any, Iterable + + + + +class pickleIO: + + def __init__(self,fileName:str,data: Any = None) -> None: + '''简单的pickle操作功能''' + self.file = fileName + if data: + self._data = data + else: + with open (self.file, 'rb') as f: + self._data = pickle.load(f) + + def __call__(self, *args: Any, **kwds: Any) -> Any: + return self.data + + def write(self): + '''将数据写入pickle''' + with open (self.file, 'wb') as f: + pickle.dump(self._data, f) + + + def load(self) -> Any: + '''从文件读取数据''' + with open (self.file, 'rb') as f: + self._data = pickle.load(f) + return self.data + + @property + def data(self): + '''返回数据值''' + if self._data is None: + raise ValueError('无可用值载入或值为None') + else: + return self._data + + + +class jsonIO: + + def __init__(self,fileName:str,data: Any = None) -> None: + '''简单的json操作功能''' + self.file = fileName + if data: + self._data = data + else: + with open (self.file, 'r', encoding='utf-8') as f: + self._data = json.load(f) + + def __call__(self, *args: Any, **kwds: Any) -> Any: + return self.data + + def write(self): + '''将数据写入json''' + with open (self.file, 'w', encoding='utf-8') as f: + json.dump(self._data, f) + + + def load(self) -> Any: + '''从文件读取数据''' + with open (self.file, 'r', encoding='utf-8') as f: + self._data = json.load(f) + return self.data + + @property + def data(self): + '''返回数据值''' + return self._data + + +class uniteIO: + + def __init__(self,fileName:str,fileType = None,data: Any = None) -> None: + '''简单的文件数据IO操作功能''' + self.filename = fileName + if not fileType is None: + self._type = fileType + else: + try: + with open (self.filename, 'r', encoding='utf-8') as f: + self._type = json + except: + with open (self.file, 'rb') as f: + self._type = pickle + + + + if not data is None: + self._data = data + else: + self._data = self.load() + + + def __call__(self, *args: Any, **kwds: Any) -> Any: + return self.data + + def write(self): + '''将数据写入文件''' + if self._type == json: + self._wfile = open(self.filename, 'w', encoding='utf-8') + elif self._type == pickle: + self._wfile = open(self.file, 'wb') + self._type.dump(self._data, self._wfile) + + + def load(self) -> Any: + '''从文件读取数据''' + if self._type == json: + self._rfile = open(self.filename, 'r', encoding='utf-8') + elif self._type == pickle: + self._rfile = open(self.file, 'rb') + self._data = self._type.load(self._rfile) + return self.data + + @property + def data(self): + '''返回数据值''' + return self._data + + + + + + + + + + + + + + + + + + + + +if __name__ == '__main__': + from sys import argv + + if argv[1]: + input(uniteIO(argv[1]).data) \ No newline at end of file diff --git a/msctLib/display.py b/msctLib/display.py new file mode 100644 index 0000000..fc3710e --- /dev/null +++ b/msctLib/display.py @@ -0,0 +1,326 @@ +# -*- coding: utf-8 -*- +'''音·创的GUI窗口界面显示库 +:若要使用其他界面显示,请详见: +:开发说明|指南''' + + +import tkinter as tk +import tkinter.simpledialog as sdialog +import tkinter.filedialog as fdialog +from msctLib.log import log + + +DEFAULTBLUE = (0, 137, 242) +# 0089F2 + +WEAKBLUE = (0, 161, 231) +LIGHTBLUE = (38, 226, 255) +# 26E2FF + +RED = (255, 52, 50) +PURPLE = (171, 112, 255) +GREEN = (0, 255, 33) +WHITE = (242, 244, 246) +BLACK = (18, 17, 16) + + +backgroundColor = WHITE +frontgroundColor = BLACK +loadingColor = DEFAULTBLUE +errorColor = RED +okColor = GREEN +tipsColor = PURPLE + +# 注:UI界面字体、代码字体 +fontPattern = ('DengXian Light', 'Fira Code') + + +class disp: + '''音·创 的基本Tk窗口显示库''' + + def __init__( + self, + root: tk.Tk = tk.Tk(), + debug: bool = False, + title: str = '音·创', + geometry: str = '0x0', + iconbitmap: tuple = ('', ''), + menuWidget: dict = {}, + wordView: str = '音·创 Musicreater', + buttons: list = [], + settingBox: list = [], + notemap: list = [], + infobar:str = '就绪', + ) -> None: + '''使用参数建立基本的 音·创 窗口 + :param root 根窗口 + :param debug 是否将日志输出到控制台 + :param title 窗口标题 + wordview: str #言论部分显示的字样 + button: list = [ # 操作按钮部分 + dict = { + 按钮名称 : tuple(按钮图标,执行函数) + }, + ], + settingbox: list = [ # 设置部分显示的字样及其对应的设置函数 + ( + 设置名称:str, + 值类型:tuple, + 显示内容:str, + 设置操作函数:, + ) + ], + map: list = [ # 一首曲目的音符数据 + 音符数据 + ] + :param infobar 显示信息用 + ''' + + # 载入参量 注意!图标将不被载入参数 + self.__root = root + '''窗口根''' + + self.title = title + '''窗口标题''' + + self.menuWidgets = menuWidget + '''菜单设定项''' + + self.wordView = wordView + '''言·论''' + + self.buttons = buttons + '''快捷功能按钮''' + + self.settingBox = settingBox + '''设置框''' + + self.notemap = notemap + '''音符列表''' + + self.infoBar = infobar + '''信息显示版''' + + + + self.debug = debug + '''是否打开调试模式''' + + self.setTitle() + self.setGeometry(geometry) + self.setIcon(*iconbitmap) + + self.setMenu() + + self.initWidget() + + # ========================================================= + # 设定函数部分 + # ========================================================= + + def setTitle(self) -> None: + '''设置窗口标题''' + self.__root.title = self.title + if self.debug: + log(f"设置窗口标题{self.title}") + + def setGeometry(self,geometry:str = '0x0') -> None: + '''设置窗口大小''' + self.__root.geometry(geometry) + if self.debug: + log(f"设置窗口大小{geometry}") + + def setIcon( + self, bitmap: str = './musicreater.ico', default: str = '' + ) -> None: + '''设置窗口图标 + 注意,default参数仅在Windows下有效,其意为将所有没有图标的窗口设置默认图标 + 如果在非Windows环境使用default参数,一个Error将被升起''' + if not self.debug: + try: + if default: + self.__root.iconbitmap(bitmap, default) + log(f'设置图标为{bitmap},默认为{default}') + else: + self.__root.iconbitmap(bitmap) + log(f'设置图标为{bitmap}') + return True + except Exception as e: + log(str(e), 'ERROR') + return False + else: + self.__root.iconbitmap(bitmap, default) + return + + def setMenu(self) -> None: + '''设置根菜单''' + if not self.menuWidgets: + # 如果传入空参数则返回当前菜单 + try: + return self.RootMenu + except Exception as E: + if self.debug: + raise E + else: + log('无法读取菜单信息', 'WARRING') + # 如果不是空参数则新建菜单 + self.RootMenu = {} + self.mainMenuBar = tk.Menu(self.__root) + for menuName, menuCmd in self.menuWidgets.items(): + # 取得一个菜单名和一堆菜单函数及其显示名称 + menu = tk.Menu(self.mainMenuBar, tearoff=0) + for cmdName, cmdFunc in menuCmd.items(): + if cmdName: + menu.add_command(label=cmdName, command=cmdFunc) + else: + menu.add_separator() + self.mainMenuBar.add_cascade(label=menuName, menu=menu) + self.RootMenu[menuName] = menu + self.__root.config(menu=self.mainMenuBar) + + def addMenu(self, menuRoot: str = '', menuLabel: str = '', menuCommand=None): + '''增加一个菜单项 + :param menuRoot : str + 菜单的根菜单,即所属的菜单上的文字 + :param menuLabel : str + 所需要增加的项目显示的文字 + :param menuCommand : + ''' + if menuRoot in self.RootMenu.keys: + # 如果已经有父菜单 + if menuLabel: + # 增加菜单指令 + self.RootMenu[menuRoot].add_command( + label=menuLabel, command=menuCommand + ) + else: + # 增加分隔栏 + self.RootMenu[menuRoot].add_separator() + else: + # 没有父菜单则新增一个父菜单 + menu = tk.Menu(self.mainMenuBar, tearoff=False) + if menuLabel: + menu.add_command(label=menuLabel, command=menuCommand) + else: + menu.add_separator() + self.mainMenuBar.add_cascade(label=menuRoot, menu=menu) + self.RootMenu[menuRoot] = menu + + def initWidget(self,) -> None: + '''设置窗口小部件,分为: + :言·论 WordView + :快捷按钮面板 ButtonBar + :设置框 SettingBar + :音轨框 TrackBar + :各个音轨的显示框 TrackFrame + :信息显示版 InfoBar + ''' + self._wordviewBar = tk.Label( + self.__root, bg='white', fg='black', text=self.wordView, font=(fontPattern[0], 30) + ) + + self.setWordView(self.wordView) + + def setWordView(self, text: str) -> None: + self._wordviewBar['text'] = text + + + # ========================================================= + # 预置函数部分 + # ========================================================= + + def authorWindowStarter( + authors: tuple = ( + ('金羿', 'Email EillesWan@outlook.com', 'QQ 2647547478'), + ('诸葛亮与八卦阵', 'QQ 474037765'), + ) + ): + '''自定义作者界面''' + from languages.lang import _ + from languages.lang import DEFAULTLANGUAGE + from msctLib.buildIN import version + + authorWindow = tk.Tk() + authorWindow.title(_('关于')) + authorWindow.geometry('550x600') # 像素 + tk.Label(authorWindow, text='', font=('', 15)).pack() + tk.Label(authorWindow, text=_('F音创'), font=('', 35)).pack() + tk.Label( + authorWindow, + text='{} {}'.format(version.version[1] + version.version[0]), + font=('', 15), + ).pack() + # pack 的side可以赋值为LEFT RTGHT TOP BOTTOM + # grid 的row 是列数、column是行排,注意,这是针对空间控件本身大小来的,即是指向当前控件的第几个。 + # place的 x、y是(x,y)坐标 + tk.Label( + authorWindow, + image=tk.PhotoImage(file='./resources/RyounLogo.png'), + width=200, + height=200, + ).pack() + tk.Label(authorWindow, text=_('凌云pairs'), font=('', 20)).pack() + tk.Label(authorWindow, text='', font=('', 15)).pack() + tk.Label(authorWindow, text=_('开发者'), font=('', 15)).pack() + for i in authors: + for j in i: + tk.Label( + authorWindow, + text=j, + font=( + '', + 17 if i.index(j) == 0 else 15, + 'bold' if i.index(j) == 0 else '', + ), + ).pack() + tk.Label(authorWindow, text='', font=('', 5)).pack() + if DEFAULTLANGUAGE != 'zh-CN': + tk.Label(authorWindow, text=_('译者'), font=('', 15)).pack() + for i in _('TRANSLATERS').split(';'): + for j in i.split(','): + tk.Label( + authorWindow, + text=j, + font=( + '', + 17 if i.split(',').index(j) == 0 else 15, + 'bold' if i.split(',').index(j) == 0 else '', + ), + ).pack() + + def exitAboutWindow(): + authorWindow.destroy() + + tk.Button(authorWindow, text=_('确定'), command=exitAboutWindow).pack() + + authorWindow.mainloop() + + +class ProgressBar: + def __init__( + self, + root: tk.Tk = tk.Tk(), + style: tuple = (DEFAULTBLUE, BLACK, WHITE), + type: bool = False, + info: str = '', + debug: bool = False, + ) -> None: + '''建立一个进度条或者加载等待界面 + :param root : tk.Tk + 建立进度条的根窗口 + :param style : tuple + 设置主题颜色,第一个参数为进度条或者等待转圈圈的颜色,第二个参数为前景色,第三个是背景色 + :param type : bool + 类型,为 False 时为进度条,为 True 时为等待板 + :param info : str + 显示的附加信息 + :param debug : bool + 是否输出日志到控制台''' + self.root = root + + +if __name__ == '__mian__': + import os + + os.chdir('../') + disp.authorMenu() diff --git a/msctLib/function.py b/msctLib/function.py new file mode 100644 index 0000000..88cafaa --- /dev/null +++ b/msctLib/function.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +'''音·创的内置功能库 +:若要加入其他功能,详见: +:开发说明|指南''' + + diff --git a/msctLib/log.py b/msctLib/log.py new file mode 100644 index 0000000..3352f13 --- /dev/null +++ b/msctLib/log.py @@ -0,0 +1,82 @@ +"""音·创的日志消息处理""" +# 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日 +# 统计:致命(三级)错误:0个;警告(二级)错误:0个;语法(一级)错误:9个 + +# 对开发者说的话: +# +# 请不要修改这里的日志,日志是给开发者和专业人士看的 +# 而不是给普通用户看的,因此,没必要使用开发者自己也 +# 不习惯的日志系统,比如说,之前诸葛亮与八卦阵 (bgArray) +# 用了 logging 库来改写我原来的日志支持,但是我反 +# 而找不到我想要的信息了,所以,日志系统给我们开发者 +# 自己看得好就可以了昂,真的别改了。而且,诸葛八卦改 +# 了之后并没有多好,喵喵喵,所以我就换回来了。我知道 +# logging 库比较常用,而且功能也好,但是我们毕竟没 +# 这个必要,就别用那个库了昂,球球了~ +# ——金羿 Eilles +# 2022 03 09 + +# To ALL the developers who will change this part: +# +# Please do NOT change anything in this file! +# The log file is only for developers or +# someone who knows a lot about our program +# to see, but not the common users. So it +# is NOT NECESSARY to use a logging system +# that we do not familiar or we do not like. +# Take bgAray “诸葛亮与八卦阵” as a example, +# he once change this `log.py` into +# logging-library-based log support system. +# But after the change had done, I could NOT +# find useful infomation according to the +# log file... So use this file but not to +# make changes PLEASE!!! I know some libraries +# like logging is usually better than the +# simple system in this file and it is normal +# to use but, I think it is not necessery, +# so PLEASE DO NOT USE OTHER LIBs TO +# OVERWRITE MY LIBRARY, THANKS. +# ——Eilles 金羿 +# 03/09/2022 + + + +import datetime,os + +#载入日志功能 +StrStartTime = str(datetime.datetime.now()).replace(':', '_')[:-7] +'''字符串型的程序开始时间''' + + +def log(info:str = '',level : str = 'INFO', isPrinted:bool = True): + '''将信息连同当前时间载入日志 + :param info : str + 日志信息 + :param level : str['INFO','WARRING','ERROR','CRASH'] + 或 int[ 1, 2, 3, 4 ] + 信息等级 + :param isPrinted : bool + 是否在控制台打印 + + :return bool + 表示是否完成任务''' + + if type(level) == type(1): + level = ['INFO','WARRING','ERROR','CRASH'][level-1] + + try: + + if not os.path.exists('./logs/'): + os.makedirs('./logs/') + + outputinfo = f'{str(datetime.datetime.now())[11:19]}-[{level}] {info}' + + with open('./logs/'+StrStartTime+'.msct.log', 'a',encoding='UTF-8') as f: + f.write(outputinfo+'\n') + + if isPrinted: + print(outputinfo) + + return True + except: + return False diff --git a/msctspt/settings.py b/msctLib/settings.py similarity index 55% rename from msctspt/settings.py rename to msctLib/settings.py index e758f09..ac9b306 100644 --- a/msctspt/settings.py +++ b/msctLib/settings.py @@ -1,18 +1,25 @@ -# -*- coding:utf-8 -*- - - - - -settings = { - 'language' : 'zh-CN', - 'theme' : { - '' : '', - }, -} - -class msctSetting: - def __init__(self,**settings) -> None: - pass - - def __call__(self, **kwds): +# -*- coding:utf-8 -*- + + +DEFAULTBLUE = (0, 137, 242) +WEAKBLUE = (0, 161, 231) +LIGHTBLUE = (38, 226, 255) +RED = (255, 52, 50) +PURPLE = (171, 112, 255) +GREEN = (0, 255, 33) +WHITE = (242, 244, 246) +BLACK = (18, 17, 16) + +settings = { + 'language' : 'zh-CN', + 'theme' : { + '' : '', + }, +} + +class msctSetting: + def __init__(self,**settings) -> None: + pass + + def __call__(self, **kwds): pass \ No newline at end of file diff --git a/msctLib/开发说明兼指南.md b/msctLib/开发说明兼指南.md new file mode 100644 index 0000000..5c51d48 --- /dev/null +++ b/msctLib/开发说明兼指南.md @@ -0,0 +1,243 @@ +开发说明\|指南 +============== + +此文件旨在使后期欲参与开发之人员减轻其开发负担,同时也为了我们正在开发的人员详细说明功能与用法 +掌握开发指南之后,在调用函数等的过程中将会更加方便 + +文件结构 +-------- + +从主文件调用display.py以实现显示,调用functions.py以使用功能 + +functions.py中会调取./addon/目录下的全部功能文件,这些功能文件必须先由./addon/addons.pkl来预先定义好 + +详细说明 +-------- + +### msctLib + +用于支持主要功能 + +#### display.py + +1. class disp + + - 参数 + + 1. `**kwgs`对窗口的基础设定 `{ '组件名称' : 函数自设定 }` 例如: + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ python + { + 'version': '0.0.1', # version指的是当前配置格式的版本 + 'title': "音·创", + 'geometry': '1200x900', + 'iconbitmap': ('./resources/musicreater.ico', './resources/musicreater.ico'), + 'menu' : { #对setMenu有特殊说明 + '文件': { + '新建': , + '打开': , + }, + }, + 'widget': { #对窗口部件又详细说明 + 'wordview':{ + 'text':'言·论', + }, + 'settingbox':{}, #后文详细说明 + 'tracklist':{}, + 'operation':{}, + 'map':{}, + }, + } + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + - 变量 + + 1. `infoBar` + + 信息显示栏,一个字符串,用于显示一些信息。 + + + 2. `title` + + 窗口标题,字符串 + + + 3. `menuWidgets` + + 对于窗口菜单的设定,其格式如下: + ```python + menuWidgets: dist = { # 菜单项目 + str"菜单名" : dict{ + str"选项名"|None : 选项函数 + }, + ... + } + ``` + + 注: + `菜单名` : `str` 显示在菜单上的字符串 + `选项名` : `str` 显示在菜单选项上的字符串 + `选项函数` : `function` 菜单调取的函数(无返回值,无入参) + 当 `选项名` 的布尔值判定为 `False` 的时候,无论 `选项函数` 为何,皆插入一段分割线,但 `选项函数` 不得为空 + + + 4. `wordView` + + 显示在言论上的文字,字符串 + + + 5. `buttons` + + 快捷功能按钮的列表,列表的元素为字典,字典的键是按钮的名称,值为一个元组,元组中含有两个元素,其中元组的第1个元素为按钮图标,是一个图片的路径;第2个元素为执行的函数,其值应当是一个函数对象。 + + ```python + button: list = [ # 操作按钮部分 + dict{ + str"按钮名称" : tuple( + 按钮图标, + 执行函数 + ) + }, + ... + ], + ``` + + + 6. `settingBox` + + 设置框,用于设置音乐的基本属性,例如词作者,曲作者等,设置格式如下: + + ```python + settingbox: list = [ #设置部分显示的字样及其对应的设置函数 + tuple( + 设置名称:str, + 值类型:tuple, + 显示内容:str, + 设置操作函数:, + ), + ... + ] + ``` + + 其中,值类型可以是如下几个项 + 1. `('str',)` 字符串类型,使用文本框输入数据 + 2. `('bool',)` 布尔类型,使用复选框输入数据 + 3. `('num',最小值:float,最大值:float,步长:float = 1)` 数值类型,使用数值滑动条输入数据 + 4. `('list',列表项:list)` 单选类型,即列表中多选一,使用单选框输入数据 + + 其中,值操作函数需要有一个参数,用于传递用户提供的设置值。 + + + 7. `notemap` + + 音符数据表,用于存储曲谱信息,存储格式如下 + ```python + notemap: list = [ # 音轨列表 + dict{ # 单个音轨 + 'instrument' : str"乐器", + 'velocity' : int 响度, + # 这里理论上需要写一个小节多少个X分音符 + # 以及小节里的都是几分音符 + # 但是这个留给以后来支持 + int 小节编号 : [ # 一个小节 + tuple( # 一个音符 + 时间 : int, + 持续 : int, + 乐器 : str, + 采样 : float, + 响度 : int, + ), + ... + ], + ... + }, + ... + ] + ``` + + 其中,对于每个音符: + 1. 时间 单位:帧 当前音符开始时,距离当前小节开始所经过的帧数 + 2. 持续 单位:帧 当前音符持续的帧数 + 3. 乐器 当前音符使用的乐器,需要在乐器列表中有所注册 + 4. 采样 当前音符在MC的采样音高(不含打击乐器) + 5. 响度 单位:格的-1次方 音符播放源距离播放者的距离的倒数 + + + - 函数 + + 1. `setMenu`对菜单的基础设定 + + ```python + { + 菜单名 : { + 选项名 : 选项函数 + } + } + ``` + + 注: + `菜单名` : `str` 显示在菜单上的字符串 + `选项名` : `str` 显示在菜单选项上的字符串 + `选项函数` : `function` 菜单调取的函数(无返回值,无入参) + 当 `选项名` 的布尔值判定为 `False` 的时候,无论 `选项函数` 为何,皆插入一段分割线,但 `选项函数` 不得为空 + + 2. `setWidget`对窗口部件的放置 + ```python + wordview: dict = { #言论部分显示的字样 + 'text': str = 显示内容, + # ... 即可用 tk.Label 的参数 + }, + button: list = [ + dict = { + 按钮名称 : tuple(按钮图标,执行函数) + }, + ], + settingbox: list = [ #设置部分显示的字样及其对应的设置函数 + ( + 设置名称:str, + 值类型:tuple, + 显示内容:str, + 设置操作函数:, + ) + ], + map: list = [ + 音符数据 + ] + ``` + 注: + + 上文中,值类型可以是如下几个项 + 1. `('str',)` 字符串类型,使用文本框输入数据 + 2. `('bool',)` 布尔类型,使用复选框输入数据 + 3. `('num',最小值:int,最大值:int,步长:int = 1)` 数值类型,使用数值滑动条输入数据 + 4. `('list',列表项:list)` 单选类型,即列表中多选一,使用单选框输入数据 + + 值得注意的是,在kwgs中修改的部件设置,可以在其变量中读取或热修改,对应的变量如下 + + | 参数 | 对应类中的变量 | 变量类型 | 说明 | + |------------|------------------|---------------------------|---------------------| + | wordview | wordview | str | 显示在 言·论 区域的文字 | + | button | button | list[dict{}] | 操作按钮 | + | settingbox | settings | list[ Any ] | 设置项目中的值 | + | tracklist | tracknum | tuple(int,int) | 当前选择到的音轨与音轨总数| + | map | notes | list[ class Note ] | 当前的音符列表 | + + + + + + + +#### ??? + +全曲的设置应该如下: +```python +标题 : str = '无名' +副标题 : str = '' +作曲 : str = '佚名' +作词 : str = '' +歌曲版权信息 : str = '' +# bpm 暂时不需要 + + +``` \ No newline at end of file diff --git a/msctplugin/pluginLoader.py b/msctplugin/pluginLoader.py new file mode 100644 index 0000000..e0163d5 --- /dev/null +++ b/msctplugin/pluginLoader.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +'''此文件为音·创的插件加载程序,为了满足各平台需求,使用的是CLI界面''' + +# W-YI 金羿 +# QQ 2647547478 +# 音·创 开发交流群 861684859 +# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com +# 版权所有 Team-Ryoun 金羿 +# 若需转载或借鉴 请附作者 + + +""" + Copyright 2022 Eilles Wan (金羿) + + 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. +""" + +# 代码写的并非十分的漂亮,还请大佬多多包涵;本软件源代码依照Apache软件协议公开 + + +# 下面为正文 + + +print(""" +音·创 插件管理 +Musicreater PLUGINS Management +""") + + + + + + + + + + + + diff --git a/msctspt/__init__.pyc b/msctspt/__init__.pyc deleted file mode 100644 index d6538b0..0000000 Binary files a/msctspt/__init__.pyc and /dev/null differ diff --git a/msctspt/__pycache__/__init__.cpython-37.pyc b/msctspt/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..7947236 Binary files /dev/null and b/msctspt/__pycache__/__init__.cpython-37.pyc differ diff --git a/msctspt/__pycache__/__init__.cpython-39.pyc b/msctspt/__pycache__/__init__.cpython-39.pyc index bcc1f74..f9a75f1 100644 Binary files a/msctspt/__pycache__/__init__.cpython-39.pyc and b/msctspt/__pycache__/__init__.cpython-39.pyc differ diff --git a/msctspt/__pycache__/bugReporter.cpython-37.pyc b/msctspt/__pycache__/bugReporter.cpython-37.pyc new file mode 100644 index 0000000..93eef16 Binary files /dev/null and b/msctspt/__pycache__/bugReporter.cpython-37.pyc differ diff --git a/msctspt/__pycache__/bugReporter.cpython-38.pyc b/msctspt/__pycache__/bugReporter.cpython-38.pyc index 618156f..cb5547d 100644 Binary files a/msctspt/__pycache__/bugReporter.cpython-38.pyc and b/msctspt/__pycache__/bugReporter.cpython-38.pyc differ diff --git a/msctspt/__pycache__/funcOpera.cpython-38.pyc b/msctspt/__pycache__/funcOpera.cpython-38.pyc index 4e3e7ff..c131e41 100644 Binary files a/msctspt/__pycache__/funcOpera.cpython-38.pyc and b/msctspt/__pycache__/funcOpera.cpython-38.pyc differ diff --git a/msctspt/__pycache__/threadOpera.cpython-37.pyc b/msctspt/__pycache__/threadOpera.cpython-37.pyc new file mode 100644 index 0000000..4d8a08f Binary files /dev/null and b/msctspt/__pycache__/threadOpera.cpython-37.pyc differ diff --git a/msctspt/__pycache__/threadOpera.cpython-39.pyc b/msctspt/__pycache__/threadOpera.cpython-39.pyc index ffda7b0..81edf5c 100644 Binary files a/msctspt/__pycache__/threadOpera.cpython-39.pyc and b/msctspt/__pycache__/threadOpera.cpython-39.pyc differ diff --git a/msctspt/__pycache__/transfer.cpython-38.pyc b/msctspt/__pycache__/transfer.cpython-38.pyc index 2e10188..88c9894 100644 Binary files a/msctspt/__pycache__/transfer.cpython-38.pyc and b/msctspt/__pycache__/transfer.cpython-38.pyc differ diff --git a/msctspt/bugReporter.py b/msctspt/bugReporter.py index d0b4f11..03cf602 100644 --- a/msctspt/bugReporter.py +++ b/msctspt/bugReporter.py @@ -4,10 +4,10 @@ # 诸葛亮与八卦阵帮忙修改语法 日期:---2022年1月19日 # 统计:致命(三级)错误:0个;警告(二级)错误:1个;语法(一级)错误:72个 import os -import zipfile def makeZip(sourceDir, outFilename, compression=8, exceptFile=None): + import zipfile """使用compression指定的算法打包目录为zip文件\n 默认算法为DEFLATED(8),可用算法如下:\n STORED = 0\n @@ -93,17 +93,17 @@ class report: class version: libraries = ( 'mido', 'amulet', 'amulet-core', 'amulet-nbt', 'piano_transcription_inference', 'pypinyin', - 'pyinstaller','py7zr','websockets', 'torch' + 'pyinstaller', 'py7zr','websockets', 'torch', 'requests', 'zhdate' ) - """当前所需库,有一些是开发用的,用户不需要安装""" + """当前所需库""" - version = ('0.1.5.1', 'Delta',) + version = ('0.1.6', 'Delta',) """当前版本""" def __init__(self) -> None: self.libraries = version.libraries - """当前所需库,有一些是开发用的,用户不需要安装""" + """当前所需库""" self.version = version.version """当前版本""" diff --git a/msctspt/transfer.py b/msctspt/transfer.py index 993b9f2..d392821 100644 --- a/msctspt/transfer.py +++ b/msctspt/transfer.py @@ -12,7 +12,7 @@ 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 +from msctLib.log import log def hans2pinyin(hans, style=3): @@ -33,11 +33,8 @@ def classList_conversion_SinglePlayer(List: list, ScoreboardName: str, playerSel commands = [] length = len(List) j = 1 - print(List) for k in range(len(List)): i = List[k][0] - print(i) - print(type(i)) try: commands.append( f"execute @a{playerSelection} ~ ~ ~ execute @s[scores={{{ScoreboardName}=" @@ -54,7 +51,6 @@ def classList_conversion_SinglePlayer(List: list, ScoreboardName: str, playerSel pass # a += List[i][1] # commands.append("\n\n# 凌云我的世界开发团队 x 凌云软件开发团队 : W-YI(金羿)\n") - print(commands) return commands @@ -222,23 +218,17 @@ def note2bdx(filePath: str, dire: list, Notes: list, ScoreboardName: str, Instru height: 生成结构的最高高度 :return 返回一个BdxConverter类,同时在指定位置生成.bdx文件""" - # from msctspt.transfer import formCmdBlock from nmcsup.trans import Note2Cmd from msctspt.bdxOpera_CP import BdxConverter cmd = Note2Cmd(Notes, ScoreboardName, Instrument, PlayerSelect, isProsess) cdl = [] - # 此处是处理一下,防止有注释 + for i in cmd: - # e = True - try: + if '#' in i: if (i[:i.index('#')].replace(' ', '') != '\n') and (i[:i.index('#')].replace(' ', '') != ''): cdl.append(i[:i.index('#')]) - # e = False - except: # ValueError + else: cdl.append(i) - # finally: - # if e is True: - # cdl.append(i) i = 0 down = False blocks = [formCmdBlock(dire, cdl.pop(0), 1, 1)] @@ -261,10 +251,7 @@ def note2bdx(filePath: str, dire: list, Notes: list, ScoreboardName: str, Instru - - - -def music2BDX(filePath: str, direction: Iterable, music: dict, isProsess: bool = False, height: int = 200, +def music2cmdBlocks(direction: Iterable, music: dict, isProsess: bool = False, height: int = 200, isSquare: bool = False): """使用方法同Note2Cmd :param 参数说明: @@ -274,10 +261,10 @@ def music2BDX(filePath: str, direction: Iterable, music: dict, isProsess: bool = isProsess: 是否显示进度条(会很卡) height: 生成结构的最高高度 isSquare: 生成的结构是否需要遵循生成正方形原则 - :return 返回一个BdxConverter类,同时在指定位置生成.bdx文件""" - from msctspt.bdxOpera_CP import BdxConverter + :return 返回一个列表,其中包含了音乐生成的所有的指令方块数据""" from msctspt.threadOpera import NewThread + allblocks = [] '''需要放置的方块''' baseDire = direction @@ -285,14 +272,15 @@ def music2BDX(filePath: str, direction: Iterable, music: dict, isProsess: bool = direction = list(direction) def trackDealing(direction,track): + print('=========DEBUG=========音轨起方块:', direction) blocks = [] cmdList = classList_conversion_SinglePlayer(track['notes'], track['set']['ScoreboardName'], music['mainset']['PlayerSelect'], isProsess) if len(cmdList) == 0: - return + return [] elif cmdList is []: - return - dire = direction + return [] + dire = direction.copy() down = False '''当前是否为向下的阶段?''' # 开头的指令方块 @@ -310,8 +298,9 @@ def music2BDX(filePath: str, direction: Iterable, music: dict, isProsess: bool = # :4 x轴负方向 无条件 # :5 x轴正方向 无条件 for cmd in cmdList: + print('=========DEBUG=========方块:', dire) blocks.append(formCmdBlock(dire, cmd, 5 if (down is False and dire[1] == height + direction[1]) or ( - down and dire[1] == direction + 1) else 0 if down else 1, 2, needRedstone=False)) + down and dire[1] == direction[1] + 1) else 0 if down else 1, 2, needRedstone=False)) if down: if dire[1] > direction[1] + 1: dire[1] -= 1 @@ -319,21 +308,46 @@ def music2BDX(filePath: str, direction: Iterable, music: dict, isProsess: bool = if dire[1] < height + direction[1]: dire[1] += 1 - if (down is False and dire[1] == height + direction[1]) or (down and dire[1] == direction + 1): + if (down is False and dire[1] == height + direction[1]) or (down and dire[1] == direction[1] + 1): down = not down dire[0] += 1 return blocks threads = [] for track in music['musics']: - threads.append(NewThread(trackDealing,(direction,track))) - threads[threads.__len__()-1].start() + threads.append(NewThread(trackDealing,(direction.copy(),track))) + threads[-1].start() direction[2] += 2 for th in threads: allblocks += th.getResult() - return BdxConverter(filePath, 'Build by Ryoun Musicreater', allblocks) + return allblocks + + + + + + + + + + + +def music2BDX(filePath: str, direction: Iterable, music: dict, isProsess: bool = False, height: int = 200, + isSquare: bool = False): + """使用方法同Note2Cmd + :param 参数说明: + filePath: 生成.bdx文件的位置 + dire: 指令方块在地图中生成的起始位置(相对位置) + music: 详见 Musicreater.py - dataset[0] + isProsess: 是否显示进度条(会很卡) + height: 生成结构的最高高度 + isSquare: 生成的结构是否需要遵循生成正方形原则 + :return 返回一个BdxConverter类,同时在指定位置生成.bdx文件""" + from msctspt.bdxOpera_CP import BdxConverter + return BdxConverter(filePath, 'Build by Ryoun Musicreater', music2cmdBlocks(direction,music,isProsess,height,isSquare) +) def note2webs(Notes: list, Instrument: str, speed: float = 5.0, PlayerSelect: str = '', isProsess: bool = False): diff --git a/nmcsup/MMFM Cpp E Develop Log.txt b/nmcsup/MMFM Cpp E Develop Log.txt new file mode 100644 index 0000000..0ec7376 --- /dev/null +++ b/nmcsup/MMFM Cpp E Develop Log.txt @@ -0,0 +1,62 @@ +ҵ硷 +C++汾־ + +ڱ˼ƻѧҵԭ򣬱ӳټƻʼд롣 + + Beta V0.1 - 20200920 +0.help +1.make +2.form +3.exit +4.ܹCDEFGABת.mcfunction +5.н + + Beta V0.2 - 20200921 +0.޸makeΪwrite +1.ôʵ +2.üƷְ +3.趨 +4.ѭģʽ趨 +5.""һֱ,޸ijΪ"ҵ纯" + + Beta V0.3 - 20200922 +0.޸writeΪmake +1.ʵ趨 +2.Ʒְ趨 +3.趨 + + Beta V0.4 - 20200923 +0.ļ趨 +1.bug:ָдļ(DE001) +2.verʾ汾Ϣ + + Beta V0.5 - 20200925 +0.޸makeΪwrite +1.趨ļ· +2.֧ɼ1234567ʾ +3.ֹ֧0 + + Beta V0.6 - 20200926 +0.޸writeΪmake +1.޸bug:ָдļ(DE001) +2.buld +3.comd +4.help򿪵İ˵һҳΪҳ +5.дڴСԶ + + Beta V0.7 - 20200927 +0.mdir,ֱ +1.ldir,Բ鿴ǰĿ¼Ϣ +3.ָlook,ʾָıļ +4.ɾ˳ʱĵȴʾ +5.bug:ʹlook鿴ļмʿ޷ʾʾ">>>"(DE002DE003) +6.bug:mdir޷ʹ(DE004) + +TO-DO Beta V0.8_ - 20200929 +0.ʵ,ڹڼԵõһйַ +1.ʵ,ڼԵõһַ +˰汾ֱ + + Beta V0.9 - 20201224 +0.޸bug:mdir޷ʹ(DE004) +1.bug:mdirһֹͣ(DE005) \ No newline at end of file diff --git a/nmcsup/MMFM Py E Development Log.txt b/nmcsup/MMFM Py E Development Log.txt new file mode 100644 index 0000000..00eaba5 --- /dev/null +++ b/nmcsup/MMFM Py E Development Log.txt @@ -0,0 +1,126 @@ +这是MMFM(我的世界函数音乐生成器)的Python版本日志 +我从2021年5月移植,中间停更了一段时间。 + + Beta V 0.0.0 +2021 5 ?15 - 2021 5 23 +1.将C++版本全部有用的功能移植至Python版本 +2.新增了可更改的音乐乐器 +3.新增了可更改的语言包Chinese +4.附带应用"jsonread - lang"可用于新增语言文本 +5.支持全部音阶,但不支持附点、X分音符等 + + Beta V 0.0.1 +2021 6 5 +1.可读取不同的语言文件,通过lang指令完成 +2.新增English语言包 +3.在输入非内部指令时以命令行运行 + + Beta V 0.0.2 +2021 6 13 +1.支持设置项保存 +2.语言设置移至设置项中 +3.新增RESET命令以重置所有设置项至默认 +4.支持休止符(“0”) +5.设置项更加人性化 + + Beta V 0.0.3 +2021 6 14 +1.支持全平台(能运行Python的平台) +2.安卓系统下不需要从源地址运行 +3.设置中给出乐器列表并需要使用在列表内的乐器 + + Beta V 0.0.4 +2021 6 14 +1.新增win指令支持窗口化输入 +2.语言包English停止支持 +3.停止支持的语言包部分将使用Chinese语言包 +4.输出结果更加人性化 +5.停止支持输入非内部命令以系统指令运行 + + Formal V 0.0.1 +2021 6 21 - 2021 6 22 +1*.支持附点、延音等时间延长谱号 +2*.支持X分音符等时间缩短谱号 +3.删除win指令支持的窗口化输入,即禁止窗口运行 +4.新增日志系统,程序运行将载入日志以便检查 +*实际上输入的时候是不支持的,只是支持了修改音符延长时间而已 + + + Formal V 0.0.2 +2121 6 22 +1.解决了字符串解析为列表时出现的问题 +2.停止调整命令行窗口大小 +3.解决了输入的音符被除重的问题 +4.buld指令建立的附加包中新增startXXX函数用于初始设定 + + + Formal V 0.0.3 +2021 6 29 +1.新增save、load指令支持工程文件存取 +2.新增default指令存储默认设置 +3.输入exit指令退出时不会保存为默认设置 +4.新增delog指令在Windows系统下删除日志文件 + + + Formal V 0.0.4 ~ 0.0.4.2 +2021 6 30 +1.支持midi解析,能够通过midi文件解析音符,且仅支持打击乐器,即音长为0的声音,不能解析音的长度,解析仅包含note_on消息而不包含note_off消息,且暂时不能解析音乐附带的其他信息 +2.新增彩蛋指令TAFTCPC(the Anniversary of the Founding of The Communist Party of China) -(0.0.4.1) +3.修复读取文件时读取内容不正确的问题 -(0.0.4.2) + + + Formal V0.0.4.3 +2021 7 1 +1.内部代码优化,更加模块化,便于以后窗口化调用 + + + Formal V0.0.5 ~ 0.0.5.2 +2021 7 3 ~ 2021 7 4 +1.支持同时编辑、生成多个音乐函数 +2.支持一个项目中保存多个文件 +3.支持同一函数中出现不同的乐器 -(0.0.5.1) +4.读取midi文件时支持音长的自动解析读取,并支持选择音轨 -(0.0.5.2) +5.修复了编辑不同乐器时出现闪退的问题 -(0.0.5.2) + + + Formal V0.0.5.3 +2021 7 5 +1.修复了存储工程文件时的崩溃问题 +2.读取midi时支持通过音轨自动生成不同的函数文件 +3.修复了生成函数文件中计分板为浮点数的问题 +4.修复文件路径不正确的问题 +5.新增应用bat脚本(仅Windows):可以快速启动、可以清除日志 +6.新增开发bat脚本(仅Windows):可以快速编译文件并启动测试、可以快速编译文件、可以快速启动测试 + + + Formal V0.0.6 +2021 7 8 - 2021 7 9 +1.停止对非Windows系统环境的支持 +2.支持预听生成的函数,即音乐试听 +3.乐曲修改设置:单个乐曲可包含多个文件序列(多个乐器),歌曲可以有自己单独的曲名、执行实体、执行计分板等独立设置;同时,每个歌曲可包含不同的乐器序列等等 +4.读取的音频格式更新:音符、我的世界音调、频率(Hz),仍是字典:'str' : [ float , float ] +5.单个项目内不包含多首歌曲,但是做了预制功能:可以编辑多个项目(现在暂时不行) +6.不可单独编辑单个音符的乐器 +7.放弃对语言文件的读取的支持 +8.停止支持对已读取的音轨的编辑(即删除edit指令) +9.停止支持全局设置的修改,以及其相关支持(即删除当前的set、reset、default指令) +10.预制支持对于单个音轨设置的修改以及音乐主设置的修改(现在暂时不行) +11.存储的项目结构变为json文件结构,则无需zipfile库 +12.生成的文件包含:支持函数(1个、循环执行)、音乐函数(多个、循环执行)、启动函数(1个、执行一次) +13.发现并修改错误:遇到休止符0时,播放会报错并停止 +14.新增彩蛋指令:RYOUN,生成团队队歌文件及项目 +15.项目更名为“我的世界函数音乐构建” + + + + + + + TO-DO +1.支持从midi文件的元信息中收取音符信息并自动生成 +2.Windows平台下支持窗口化 +3.支持使用WebSocket接口自动播放已编辑的音乐 +4.可以编辑多个项目 +5.能够自动将一个长串的音乐分成多个函数文件 +6.对于单个音轨设置的修改以及音乐主设置的修改 +7.支持汇报崩溃记录(通过邮件附件的方式) \ No newline at end of file diff --git a/nmcsup/__pycache__/__init__.cpython-37.pyc b/nmcsup/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..2871e42 Binary files /dev/null and b/nmcsup/__pycache__/__init__.cpython-37.pyc differ diff --git a/nmcsup/__pycache__/log.cpython-37.pyc b/nmcsup/__pycache__/log.cpython-37.pyc new file mode 100644 index 0000000..41528fa Binary files /dev/null and b/nmcsup/__pycache__/log.cpython-37.pyc differ diff --git a/nmcsup/__pycache__/vers.cpython-37.pyc b/nmcsup/__pycache__/vers.cpython-37.pyc new file mode 100644 index 0000000..d65d352 Binary files /dev/null and b/nmcsup/__pycache__/vers.cpython-37.pyc differ diff --git a/resources/MSCT Dev Log.txt b/resources/MSCT Dev Log.txt index d212414..ed7f103 100644 --- a/resources/MSCT Dev Log.txt +++ b/resources/MSCT Dev Log.txt @@ -1,29 +1,11 @@ 音·创(Musicreater)是由金羿(W-YI)开发的一款《我的世界》基岩版音乐生成辅助软件 -本软件源代码依照Apache软件协议公开。 +本软件源代码依照Apache 2.0软件协议公开。 Copyright © W-YI 2022 本软件是金羿前作函数音创和世界音创的集合版本,同时增加了大量功能更新。 - To-Do -1.可以导出自定义的结构文件用于存储要导入地图中的结构 -2.进度条 -3.可以将音乐写入音符盒(红乐) -4.修改UI界面使之适应当前功能 -5.支持自动给音符盒绑定更多的音色 -6.可以由.schematic文件导入地图,亦可反向处理 -7.制作软件下载器使用户更直观地操作 -8.支持自定义创建websockeet服务器播放音乐(感谢由 Fuckcraft “鸣凤鸽子”等 带来的我的世界websocket服务器功能) -9.支持使用红石播放音乐 -10.支持采用延时的播放器 -11.支持使用bdx导出结构 -12.支持采用tp的方法播放 -13.支持识别曲谱图片解析音乐 -14.支持使用瀑布流的方式播放音乐 - - -17.支持自动搜寻地图目录位置(网易&微软) =============== 2022 年度挑战 @@ -36,6 +18,29 @@ Copyright © W-YI 2022 新更新日志 + Delta 0.2.0 +2022 2 10 ~ 2022 x +1.进行了大量的代码重构,使之更加易于开发 +2.对功能进行了精简优化,能够更加方便的开发新功能 +3.完善程序的一些外观与性能优化,使用了更多多线程板块 +4.在读取和写入的时候加入进度条,会实时反馈当前的加载进度 +5.能够使用可视化界面进行音乐的基本编辑 +6.提高用户感受,修复已知问题 +7.增强个性化设置,令用户能够用其所感 +8.更新读我文档,使之更用户化 +9.面对用户的操作加强 +10.新增下载器,无需用户从源代码安装 + + + Delta 0.1.5 +2022 4 4 +0.新增金羿生日祝福 +1.修复诸多问题 +2.正在往0.2版本迭代更新 +3.预计半年之内可以发布新版本 +4.支持使用自动安装器下载安装 +5. + Delta 0.1.5.2 2022 2 1 农历大年初一 diff --git a/resources/RyounLogo.png b/resources/RyounLogo.png new file mode 100644 index 0000000..cb96d0f Binary files /dev/null and b/resources/RyounLogo.png differ diff --git a/resources/donationCode.png b/resources/donationCode.png new file mode 100644 index 0000000..4758eb7 Binary files /dev/null and b/resources/donationCode.png differ diff --git a/resources/msctIcon.png b/resources/msctIcon.png new file mode 100644 index 0000000..ecac602 Binary files /dev/null and b/resources/msctIcon.png differ diff --git a/resources/msctIcon_256px.png b/resources/msctIcon_256px.png new file mode 100644 index 0000000..3e36e97 Binary files /dev/null and b/resources/msctIcon_256px.png differ diff --git a/resources/msctIcon_512px.png b/resources/msctIcon_512px.png new file mode 100644 index 0000000..ecac602 Binary files /dev/null and b/resources/msctIcon_512px.png differ diff --git a/resources/musicreater.png b/resources/musicreater.png deleted file mode 100644 index c71a178..0000000 Binary files a/resources/musicreater.png and /dev/null differ diff --git a/resources/myWords.txt b/resources/myWords.txt index 454feca..4654dee 100644 --- a/resources/myWords.txt +++ b/resources/myWords.txt @@ -1,4 +1,4 @@ -生命灵动 当用激情跃起奋发之力 +生命灵动 当用激情跃起奋发之力 奇偶数阵 学海无涯 应用爱意徜徉 在生命的起源寻找灵魂的慰藉 @@ -34,10 +34,107 @@ 上了战场就是英雄 ——长津湖 冰与火 恨与爱 静与情 有些枪必须开,有些可以不开 ——长津湖 -夕阳西下,余辉将尽,夜幕降临,寒风凛冽 ——原神 +夕阳西下,余辉将尽\n夜幕降临,寒风凛冽 ——原神 愿风擦拭你的双眼,让你看清真相 ——原神 心愿之结晶 而何能之宝贵 神明,正倾诉着他辉煌的过去…… 一切过程与结果都不重要 重要的是热爱与真情 给大家带来笑容 这就是我存在的使命 不忘本源 牢记故地 +一厢情愿即是真 心海浮沉即为灵 +听戏时要点最红的名伶,\n遛鸟时要买最名贵的画眉\n——此即人生 ——原神 +「精巧」是千年的积淀,而其背后皆存于「意义」 +世事无常,悲喜难料 ——原神 +金钱在死亡面前毫不重要 +风雨兄弟情 +微笑面对现实 +人于磨难中练就 +Long live the People's Republic of China. +There is NO heroes, only honors. +A man achieve with challenges. +种果得果,等的就是这份收获的喜悦 ——原神 +事了拂衣去,深藏功与名 +万事开头虽难,倾注的情感也多;\n而欲永恒,仍需重新审视自身\n不小心处理,灵魂便留下裂纹无法挽回。 +历经历史的沉淀,留下希望的继承 +身为凡民,血脉脆弱,却也坚强 +民为本,社稷次之,君为轻 ——孟子 +不如归去 +你完成了你的职责,现在,去休息吧。 +一场长梦,梦醒之后,人就学会了诀别。 +你们——会祝福下一个时代吗? ——原神 +任何旅途中的旅伴同行,都会有分别的一日。 ——原神 +「永恒」最接近于天理 ——原神 +等旅途到达了终点,再考虑停留于何处吧 ——原神 +人海中相遇,本是缘分。 ——原神 +凡缘朦朦仙缘滔 +因果红尘渺渺,烟消 ——原神 +未入尘世,而心远之 +灵心而静,莫问归期 +美酒宜人,宜人的却不只是美酒。 ——原神 +戏会落幕,人生却不会。 ——原神 +历史越久远,土地上的每一件事物就会承载更多价值。 ——原神 +深邃的灵魂唤起久远的回忆 +求索之人 当为奉之 +无论前路为星辰亦或深渊,皆需往而为之 +除了路途中的花与枫叶,还有心中的「道」 ——原神 +只有败北,才能感悟差距,才有机会成长 ——原神 +命运的邂逅,必定有其意义 ——原神 +万商云来,千船继至。\n百货迭出,诸海历览。\n ——原神 +现状越是难以置信,我们越是不能停下脚步。 ——原神 +古老的文明孕育着最美丽的传说 ——原神 +百川奔流 雨露不休 +梦,随着年月流逝而不断消散 +自由之风会指引前进的路,愿你与我们同行 +绯樱若解离别苦,自当常留驻。 ——原神 +犯错受罚,天经地义 +犯的错无法偿还,那便遭人嫉恨 +恨——埋藏在深深的地底,待到发出之时,直冲人心 +城市和风是有记忆的 ——原神 +传承,永远不变 +「由浅入深」,对万物的掌握皆是如此。 ——原神 +乘风破浪,勇往直前。 +时间的长河会见证过往的一切 +风沙的吹拂会证明遗失的散漠 +深冷的面具下埋藏着颤抖的心 +苦痛的旅程中盘错着举世的谎言 +欲落的花会告诉你我无尽的思念,而风会在此刻替我拥抱住你。 ——蝶<1361223398> +仰望这深邃的夜空,明星洒下的光,总是无尽斑驳 +欲知后事如何,唯有后世来分说 ——b站BV1jm4y1S76q +曲高未必人不识,自有知音和清词 ——原神 +接引春雷焚身骨,化灰以养万类荣 ——原神 +浮世景色百千年依旧,人之在世却如白露与泡影 ——原神 +今古诸事,激荡中流,宏图待看新秀 ——原神 +烟花易逝,人情长存 ——原神 +正因为我们都是须臾之人,才更应该珍惜须臾的美好 ——原神 +如果说,生命的脚印终有一天会被时间的尘埃掩埋,那么我们就永远不能停下脚步 ——明日方舟 +只要不停下脚步,道路就会不断延伸。 ——某B站用户 +红色光芒从遥远的地平线上浮现,影月留给人间的黑暗逐渐退潮 ——明日方舟 +如果没有人有了解真相的意愿,那就算把真相撒播在街道上,也不会发芽的 ——明日方舟 +永远不要否定善行,道德和良知永远不会错 ——明日方舟 +唯独死亡不可避免,唯独生命不可辜负 ——少女前线 +人即像树,枝叶越向往明亮的天空,根须越深入幽暗的地底 ——尼采 +沉默不代表服从,生活在黑暗里,不代表放弃光明 ——少女前线 +但行前路终无悔,只盼万事在人为 ——废墟图书馆 +我忘却了所有悲剧,所见之处皆是奇迹 ——空洞骑士 +只要坚信自己的道路,就无所谓天气是晴是雨。 ——原神 +在这个真实的太过分的世界里,每个人都需要仰望星空 ——原神 +当你重新踏上旅途之后,一定要记得旅途本身的意义 ——原神 +识花鸟之一趣,照月风之长路 ——原神 +只要不失去你的崇高,整个世界都会向你敞开 ——原神 +每个人都是一个自己的精神支柱 ——GitHub Copliot +I am a dreamer, but I am not a dreamer. ——GitHub Copliot +The only thing that makes a dream impossible is the fear of failure. ——GitHub Copliot +A dream is a wish that you have or something that you have dreamed of in your mind. ——GitHub Copliot +It is not the strongest of the species that survives, nor the most intelligent, nor the fastest. ——GitHub Copliot +To be a dreamer is to be a free spirit. ——GitHub Copliot +To be or not to be is a question. ——莎士比亚 +即使身躯残破,也要在战场上拼杀到最后一刻,要战斗到流干最后一滴血为止。 ——原神 +朋友之间,也许就是要心知肚明才好 ——原神 +轻盈的风,偶尔也会变得沉重…虽然,只是凡人难以察觉的短短一瞬 ——原神 +我听过树的歌、乌云和雨的歌、遥远北方的青色飞龙悠远的吟唱,也听过我降落在地面上时,狐、兔,和地里的虫颤抖的协奏 ——原神 +无人来书写我们的故事,我们就是故事本身。 +故事的种子是生活与旅行 ——原神 +每个人的「生活(故事)」,都只属于自己… ——原神 +如果我们要再会,就在夕阳与海面相遇的地方再会吧。 ——原神 +到那时,再让我看看你如同钻石一般明净而璀璨的灵魂,是否蒙上了一缕尘埃吧。 ——原神 +水过时迁 diff --git a/查看代码数.py b/查看代码数.py index 9683985..4887557 100644 --- a/查看代码数.py +++ b/查看代码数.py @@ -12,10 +12,9 @@ for path, dir_list, file_list in os.walk(r"./"): 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.startswith('#'): + continue if code: print("\t" + code) m += 1 diff --git a/测试用/1.msct b/测试用/1.msct deleted file mode 100644 index 8857f37..0000000 Binary files a/测试用/1.msct and /dev/null differ