commit d5c4e5c874ca3b8edec470072e2057ffb4ee649e Author: Eilles <71250018+EillesWan@users.noreply.github.com> Date: Sun Nov 21 01:21:41 2021 +0800 先传个主题看看 diff --git a/Musicreater.py b/Musicreater.py new file mode 100644 index 0000000..0227c28 --- /dev/null +++ b/Musicreater.py @@ -0,0 +1,1297 @@ +# -*- coding: utf-8 -*- + + +# W-YI 金羿 +# QQ 2647547478 +# 音·创 开发交流群 861684859 +# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com +# 版权所有 Team-Ryoun 金羿 +# 若需转载或借鉴 请附作者 + + +# 代码写的并非十分的漂亮,还请大佬多多包涵;本软件源代码依照Apache软件协议公开 + + +import json +import os +import shutil +import threading +import tkinter as tk +import tkinter.filedialog +import tkinter.messagebox +import tkinter.simpledialog + +from msctspt.threadOpera import NewThread +from nmcsup.vers import VER + + + + + +__version__ = VER[1]+VER[0] +__author__ = 'W-YI (金羿)' + + + + + +import sys + +if sys.platform != 'win32': + print("您当前的运行环境不符合要求。") + print(__author__+" 音·创 当前版本"+__version__) + print("按下回车退出程序") + input() + exit() + + + + + +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':{ + 'PackName':"Ryoun", + 'MusicTitle':'Noname', + 'IsRepeat':False, + 'PlayerSelect':'' + }, + 'musics':[ + { + 'set':{ + 'EntityName':'music_support', + 'ScoreboardName':'music_support', + 'Instrument':'harp', + 'FileName':"Music" + }, + 'notes':[ + [0.0,1.0], + ] + }, + ], + }, + ] +''' + + + +dataset = [ + { + 'mainset': { + 'PackName': "Ryoun", + 'MusicTitle': 'Noname', + 'IsRepeat': False, + 'PlayerSelect': '' + }, + 'musics': [ + { + 'set': { + 'EntityName': 'MusicSupport', + 'ScoreboardName': 'MusicSupport', + 'Instrument': 'note.harp', + 'FileName': "Music" + }, + 'notes': [ + [0.0, 1.0], + ] + }, + ], + }, +] + + +is_new_file = True +is_save = True +ProjectName = '' +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 + 若需转载或借鉴 请附作者\n + ''' + + print("音·创 正在启动……") + + ''' + from nmcsup.vers import chkver + print("检验或下载支持库") + chkver() + ''' + + + + print("更新执行位置...") + os.chdir(__file__[:len(__file__)-__file__[len(__file__)::-1].index('\\')]) + print('完成!') + + + + + print('载入日志功能...') + from nmcsup.log import log + print('完成!') + + + + + # 读取文件 + + + print("载入文件读取函数") + + def ReadFile(fn:str) -> list: + from nmcsup.nmcreader import ReadFile as fileRead + k = fileRead(fn) + if k == False : + tk.messagebox.showerror(title='错误', message="找不到文件😢:"+fn) + return + else: + return k + + + def ReadMidi(midfile:str) -> str: + from nmcsup.nmcreader import ReadMidi as midiRead + k = midiRead(midfile) + if k == False : + tk.messagebox.showerror(title='错误', message="找不到文件或无法读取文件😢:"+midfile) + return + else: + return k + + + print('完成!') + + + + + # 菜单命令 + print('加载菜单命令...'); + + def exitapp(): + global is_save + if is_save != True: + result = tkinter.messagebox.askyesno(title='提示', message='您当前的项目已修改但未存储,是否先保存当前项目?') + log('询问是否存储:'+str(result)) + if result: + SaveProject() + log("程序正常退出") + if clearLog : + print("清除log(此句不载入日志)") + try: + shutil.rmtree("./log/") + except: + pass; + try: + shutil.rmtree("./logs/") + except: + pass; + try: + shutil.rmtree("./cache/") + except: + pass; + + + + try: + global dataset + del dataset + except: + pass; + + global root + root.destroy() + del root + exit() + + + print('退出命令加载完成!') + + + + def SaveProject(): + if is_new_file: + # 新的项目相等于另存为 + SaveAsProject() + return + else: + # 旧项目旧存着吧 + log("存储已有文件:"+ProjectName) + with open(ProjectName, 'w') as f: + json.dump(dataset[0], f) + tkinter.messagebox.showinfo(title='已存储', message='项目已经存储至:'+ProjectName) + global is_save + is_save = True + + + print('保存项目命令加载完成!') + + + def SaveAsProject(): + # 另存为项目 + log("另存项目") + fn = tkinter.filedialog.asksaveasfilename(title='新建 音·创 项目', initialdir=r'./', filetypes=[('音·创工程文件', '.msct'), ('任意类型', '*')], defaultextension='Noname.msct') + if fn == None or fn =='': + log("取消") + return + ProjectName = fn + log("新建文件:"+ProjectName) + with open(ProjectName, 'w') as f: + json.dump(dataset[0], f) + tkinter.messagebox.showinfo(title='已存储', message='项目已经存储至:'+ProjectName) + global is_save + is_save = True + + + print('另存项目命令加载完成!') + + + def openOldProject(): + log("打开旧版本项目") + global is_save + if is_save != True: + result = tkinter.messagebox.askyesno(title='提示', message='您当前的项目已修改但未存储,是否先保存当前项目?') + log('询问是否存储:'+str(result)) + if result: + SaveProject() + fn = tkinter.filedialog.askopenfilename(title='请选择旧类型的项目', initialdir=r'./', filetypes=[('函数音创工程文件', '.ry.nfc'), ('MMFM0.0.6版本工程文件', '.ry.mfm'), ('全部类型', '*')], multiple=True) + if fn == None or fn == '': + log("取消") + return + else: + fn = fn[0] + log("读取文件:"+fn) + from nmcsup.nmcreader import ReadOldProject + dataset[0] = ReadOldProject(fn) + + + + def openProject(): + log("打开音·创项目") + global is_save + if is_save != True: + result = tkinter.messagebox.askyesno(title='提示', message='您当前的项目已修改但未存储,是否先保存当前项目?') + log('询问是否存储:'+str(result)) + if result: + SaveProject() + fn = tkinter.filedialog.askopenfilename(title='请选择 音·创 项目', initialdir=r'./', filetypes=[('音·创工程文件', '.msct'),('全部类型', '*')], multiple=True) + if fn == None or fn == '': + log("取消") + return + else: + fn = fn[0] + log("读取文件:"+fn) + try: + with open(fn, 'r', encoding='UTF-8') as c: + dataset[0] = json.load(c) + except: + print('找不到文件:'+fn+",请查看您是否输入正确") + log("丢失"+fn) + 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(u'音·创 - 关于') + aabw.geometry('400x600') # 像素 + tk.Label(aabw, text='', font=('', 15)).pack() + tk.Label(aabw, text='我的世界音·创', font=('', 35)).pack() + tk.Label(aabw, text='当前版本:'+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='凌云我的世界开发团队', font=('', 20)).pack() + tk.Label(aabw, text='×', font=('', 20)).pack() + tk.Label(aabw, text='凌云软件开发团队', font=('', 20)).pack() + tk.Label(aabw, text='', font=('', 15)).pack() + tk.Label(aabw, text='唯一开发者:金羿(W-YI)', font=('', 15)).pack() + tk.Label(aabw, text='Email: EillesWan@outlook.com', font=('', 15)).pack() + tk.Label(aabw, text='QQ: 2647547478', font=('', 15)).pack() + tk.Label(aabw, text='讨论群: 861684859', font=('', 15)).pack() + + aabw.mainloop() + + + print('关于命令加载完成!') + + + def apphelp(): + ahpw = tk.Tk() + ahpw.title(u'音·创 - 帮助') + ahpw.geometry('400x600') # 像素 + + ahpw.mainloop() + + print('帮助命令加载完成!') + + + + def FromMP3(): + log("从MP3导入音乐"); + mp3file = tkinter.filedialog.askopenfilename(title='请选择钢琴声音的 MP3 文件', initialdir=r'./', filetypes=[('钢琴声音的MP3', '.mp3'), ('全部类型', '*')], multiple=True) + if mp3file == None or mp3file == '': + log("取消") + return + else: + mp3file = mp3file[0] + log("转换mp3文件"+mp3file) + 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 FromMidi(): + log("从midi导入音乐") + midfile = tkinter.filedialog.askopenfilename(title='请选择 MIDI 文件', initialdir=r'./', filetypes=[('Midi文件', '.mid .midi'), ('全部类型', '*')], multiple=True) + if midfile == None or midfile == '': + log("取消") + return + else: + midfile = midfile[0] + log("开新线程打开midi文件"+midfile) + th = NewThread(ReadMidi, (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 + + + print('读midi命令加载完成!') + + + def FromForm(): + log("从文本读入音轨") + fn = tkinter.filedialog.askopenfilename(title='请选择 音符文本 文件', initialdir=r'./', filetypes=[('文本文件', '.txt'), ('全部类型', '*')], multiple=True) + if fn == None or fn =='': + log("取消") + return + else: + fn = fn[0] + log("打开音符文件"+fn) + 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='获取信息', prompt='请输入音符:', initialvalue='`1 .2 C') + if dat == None: + return + datas = [] + for i in dat.split(" "): + datas.append([str(i), 1.0]) + log('音符数据写入'+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('写入命令加载完成!') + + + + 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='请选择文件生成的位置', initialdir=r'./') + if file == None or file =='': + log("取消") + return; + else: + makeFuncFiles(dataset[0], file+'/') + + + def MakeCMDdir(): + log("生成函数包") + from msctspt.funcOpera import makeFunDir + file = tkinter.filedialog.askdirectory(title='请选择文件夹生成的位置', initialdir=r'./') + if file == None or file =='': + log("取消") + return; + else: + makeFunDir(dataset[0], file+'/') + + + def MakePackFile(): + file = tkinter.filedialog.askdirectory(title='请选择.mcpack文件生成的位置', initialdir=r'./') + if file == 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/'+dataset[0]['mainset']['PackName'] +"Pack/behavior_packs/"+dataset[0]['mainset']['PackName']+"/functions",'./') + shutil.move('./temp/'+dataset[0]['mainset']['PackName'] +"Pack/behavior_packs/"+dataset[0]['mainset']['PackName']+"/manifest.json",'./') + with zipfile.ZipFile(file+'/'+dataset[0]['mainset']['PackName']+'.mcpack', "w") as zipobj: + for i in os.listdir('./functions/'): + zipobj.write('./functions/'+i) + zipobj.write('./manifest.json') + shutil.move('./functions','./temp/') + shutil.move('./manifest.json','./temp/') + shutil.rmtree("./temp/") + + + + + + + #转为空方块世界 + def ToBlockWorldEpt(): + import zipfile + + from nmcsup.trans import Cmd2World, Datas2BlkWorld, Notes2Player + while True: + try: + dire = tkinter.simpledialog.askstring(title = '坐标信息输入',prompt='请输入坐标:',initialvalue = '16 4 16') + if dire == None or dire == '': + return; + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except: + tkinter.messagebox.showerror(title="错误❌", message="您输入的格式有误,请重新输入!"); + continue + break + Outdire = tkinter.filedialog.askdirectory(title='请选择世界文件夹生成的位置', initialdir=r'./'); + if Outdire == None or Outdire == '': + log("取消") + return; + else: + Outdire = Outdire[0]+'/'+dataset[0]['mainset']['PackName']+'/'; + with zipfile.ZipFile("./nmcsup/EptWorld.zip", "r") as zipobj: + 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 + while True: + try: + dire = tkinter.simpledialog.askstring(title = '坐标信息输入',prompt='请输入坐标:',initialvalue = '16 4 16') + if dire == None or dire == '': + return; + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except: + tkinter.messagebox.showerror(title="错误❌", message="您输入的格式有误,请重新输入!"); + continue + break + Outdire = tkinter.filedialog.askdirectory(title='请选择世界文件夹生成的位置', initialdir=r'./'); + if Outdire == 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(): + while True: + try: + dire = tkinter.simpledialog.askstring(title = '坐标信息输入',prompt='请输入坐标:',initialvalue = '16 4 16') + if dire == None or dire == '': + return; + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except: + tkinter.messagebox.showerror(title="错误❌", message="您输入的格式有误,请重新输入!"); + continue + break + Outdire = tkinter.filedialog.askdirectory(title='请选择函数包生成的位置', initialdir=r'./'); + if Outdire == None or Outdire == '': + return; + else: + 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 + + from nmcsup.trans import Cmd2World, Note2Cmd + while True: + try: + dire = tkinter.simpledialog.askstring(title = '坐标信息输入',prompt='请输入坐标:',initialvalue = '16 4 16'); + if dire == None or dire == '': + return; + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])]; + except: + tkinter.messagebox.showerror(title="错误❌", message="您输入的格式有误,请重新输入!"); + continue; + break; + Outdire = tkinter.filedialog.askdirectory(title='请选择世界文件夹生成的位置', initialdir=r'./'); + if Outdire == None or Outdire == '': + return; + else: + Outdire+='/'+dataset[0]['mainset']['PackName']+'/'; + with zipfile.ZipFile("./nmcsup/EptWorld.zip", "r") as zipobj: + 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(): + from nmcsup.trans import Cmd2World, Note2Cmd + while True: + try: + dire = tkinter.simpledialog.askstring(title = '坐标信息输入',prompt='请输入坐标:',initialvalue = '16 4 16') + if dire == None or dire == '': + return; + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except: + tkinter.messagebox.showerror(title="错误❌", message="您输入的格式有误,请重新输入!"); + continue + break + Outdire = tkinter.filedialog.askdirectory(title='请选择世界文件夹生成的位置', initialdir=r'./'); + if Outdire == 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 + while True: + try: + dire = tkinter.simpledialog.askstring(title = '坐标信息输入',prompt='请输入坐标:',initialvalue = '16 4 16') + if dire == None or dire == '': + return; + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except: + tkinter.messagebox.showerror(title="错误❌", message="您输入的格式有误,请重新输入!"); + continue + break + Outdire = tkinter.filedialog.askdirectory(title='请选择世界文件夹生成的位置', initialdir=r'./'); + if Outdire == None or Outdire == '': + return; + else: + Outdire+='/'; + Cmd2World(open(tkinter.filedialog.askopenfilename(title='请选择 .mcfunction 文件', initialdir=r'./', filetypes=[('我的世界指令函数文件', '.mcfunction'), ('全部类型', '*')], multiple=True)[0],'r',encoding='utf-8').readlines(),Outdire,dire) + + + + + #大函数分割并载入执行链 + def bigFunc2World(): + log("分割大函数") + 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 = '坐标信息输入',prompt='请输入执行链生成坐标:',initialvalue = '16 4 16'); + if dire == None or dire == '': + return; + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])]; + except: + tkinter.messagebox.showerror(title="错误❌", message="您输入的格式有误,请重新输入。"); + continue + break + Outdire = tkinter.filedialog.askdirectory(title='请选择世界文件夹生成的位置', initialdir=r'./'); + if Outdire == None or Outdire == '': + log("取消") + return; + else: + Outdire+='/'; + log("获得地图地址:"+Outdire) + fileName = tkinter.filedialog.askopenfilename(title='请选择 .mcfunction 文件', initialdir=r'./', filetypes=[('我的世界指令函数文件', '.mcfunction'), ('全部类型', '*')], multiple=True) + if fileName == 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="错误❌", message="您的函数文件不大于10k条指令,无需进行分割操作。"); + return; + log("创建函数文件夹") + packName = fileName[len(fileName)-fileName[::-1].index('/'):fileName.index('.')] + packDire = hans2pinyin(packName) + try: + os.makedirs(Outdire+"behavior_packs/"+packDire+"/functions/"); + except: + 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(): + from msctspt.transfer import note2bdx + while True: + try: + dire = tkinter.simpledialog.askstring(title = '坐标信息输入',prompt='请输入执行链生成相对坐标:',initialvalue = '0 0 0'); + if dire == None or dire == '': + return; + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])]; + except: + tkinter.messagebox.showerror(title="错误❌", message="您输入的格式有误,请重新输入。"); + continue + break + + fileName = tkinter.filedialog.asksaveasfilename(title='请选择需要生成的.bdx文件', initialdir=r'./', filetypes=[('FastBuilder结构文件', '.bdx'), ('全部类型', '*')], defaultextension=dataset[0]['mainset']['PackName']+'.bdx',initialfile=dataset[0]['mainset']['PackName']+'.bdx') + if fileName == 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("生成结果",'转换结束!\n'+str(res)) + + + + + def wsPlay(): + from msctspt.transfer import note2webs + spd = tkinter.simpledialog.askfloat("输入播放速度",prompt='一秒,音乐走几拍?',initialvalue = '5.0') + tkinter.messagebox.showinfo(title="创建中", message="请在游戏中使用connect指令连接localhost:8080,即可播放"); + note2webs(dataset[0]['musics'][NowMusic]['notes'],dataset[0]['musics'][NowMusic]['set']['Instrument'],spd,dataset[0]['mainset']['PlayerSelect']) + + + + + + def toRSworldEPT(): + import zipfile + + from msctspt.transfer import note2RSworld + while True: + try: + dire = tkinter.simpledialog.askstring(title = '坐标信息输入',prompt='请输入坐标:',initialvalue = '16 4 16'); + if dire == None or dire == '': + return; + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])]; + except: + tkinter.messagebox.showerror(title="错误❌", message="您输入的格式有误,请重新输入!"); + continue; + break; + Outdire = tkinter.filedialog.askdirectory(title='请选择世界文件夹生成的位置', initialdir=r'./'); + if Outdire == None or Outdire == '': + return; + else: + Outdire+='/'+dataset[0]['mainset']['PackName']+'/'; + with zipfile.ZipFile("./nmcsup/EptWorld.zip", "r") as zipobj: + 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 + while True: + try: + dire = tkinter.simpledialog.askstring(title = '坐标信息输入',prompt='请输入坐标:',initialvalue = '16 4 16') + if dire == None or dire == '': + return; + dire = [int(dire.split(' ')[0]), int(dire.split(' ')[1]), int(dire.split(' ')[2])] + except: + tkinter.messagebox.showerror(title="错误❌", message="您输入的格式有误,请重新输入!"); + continue + break + Outdire = tkinter.filedialog.askdirectory(title='请选择世界文件夹生成的位置', initialdir=r'./'); + if Outdire == 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; + + + + + + + + + + #使用邮件反馈bug + def sendBugReport(): + from msctspt.bugReporter import emailReport + name = tkinter.simpledialog.askstring(title = '邮件反馈信息输入',prompt='您的称呼') + contact = tkinter.simpledialog.askstring(title = '邮件反馈信息输入',prompt='您的联系方式') + describetion = tkinter.simpledialog.askstring(title = '邮件反馈信息输入',prompt='您对问题的描述') + emailReport(name,contact,describetion); + del name,contact,describetion + + + + + + + + + + + + def ClearLog(): + global clearLog; + clearLog = not clearLog; + if clearLog: + tkinter.messagebox.showinfo("完成!✔",'在程序结束后将清除日志及临时文件信息。'); + else: + tkinter.messagebox.showinfo("完成!✔",'在程序结束后将不会清除日志及临时文件信息。'); + + + + + print('生成部分及其余命令加载完成!'); + + + print('完成!'); + + # 窗口部分 + print('增加窗口元素...'); + global root + + root.title(u'音·创 - 金羿 - '+VER[1]+VER[0]); + root.geometry('800x800'); # 像素 + + print('完成!') + + + print('加载点击与页面更新命令...') + + # 音轨菜单被点击 + + + def MusicList_selected(event): + global NowMusic + NowMusic = ListMusicList.get(ListMusicList.curselection()) + log('刷新音轨'+str(NowMusic)) + RefreshMusic(NowMusic) + + + # 音符菜单被点击 + def NoteList_selected(event): + pass # 编辑音符操作 + + + def CMDList_selected(event): + pass # 命令编辑操作 + + + print('菜单点击命令加载完成!') + + + # 刷新音轨部分 + def RefreshMusic(Music=0): + LabelEntityName['text'] = '执行实体名: ' + dataset[0]['musics'][Music]['set']['EntityName'] + LabelScoreboardName['text'] = '使用计分板: ' + dataset[0]['musics'][Music]['set']['ScoreboardName'] + LabelInstrument['text'] = '所用的乐器: ' + dataset[0]['musics'][Music]['set']['Instrument'] + LabelFileName['text'] = '当前音轨名: ' + 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'] = '包名: '+dataset[0]['mainset']['PackName'] + LabelMusicTitle['text'] = '音乐标题: '+dataset[0]['mainset']['MusicTitle'] + LabelIsRepeat['text'] = '是否重复: '+str(dataset[0]['mainset']['IsRepeat']) + LabelPlayerSelect['text'] = '玩家选择器:'+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): + dataset[0]['mainset']['PackName'] = tkinter.simpledialog.askstring(title='修改主设置', prompt='修改包名', initialvalue='Ryoun') + RefreshMain() + + + def changeMusicTitle(event): + dataset[0]['mainset']['MusicTitle'] = tkinter.simpledialog.askstring(title='修改主设置', prompt='修改音乐标题', initialvalue='Noname') + RefreshMain() + + + def changeIsRepeat(event): + dataset[0]['mainset']['IsRepeat'] = not dataset[0]['mainset']['IsRepeat'] + RefreshMain() + + + def changePlayerSelect(event): + dataset[0]['mainset']['PlayerSelect'] = tkinter.simpledialog.askstring(title='修改主设置', prompt='修改玩家选择器\n注意!要加上中括号[]', initialvalue='') + if not dataset[0]['mainset']['PlayerSelect']: + dataset[0]['mainset']['PlayerSelect'] = '' + RefreshMain() + + + def changeEntityName(event): + global NowMusic + dataset[0]['musics'][NowMusic]['set']['EntityName'] = tkinter.simpledialog.askstring(title='修改节设置', prompt='修改本音轨的执行实体名:', initialvalue='musicSupport') + RefreshMusic(NowMusic) + + + def changeScoreboardName(event): + global NowMusic + dataset[0]['musics'][NowMusic]['set']['ScoreboardName'] = tkinter.simpledialog.askstring(title='修改节设置', prompt='修改本音轨所用的积分板:', initialvalue='musicSupport') + RefreshMusic(NowMusic) + + + def changeInstrument(event): + from nmcsup.const import Instuments as inst + global NowMusic + while(True): + instemp = tkinter.simpledialog.askstring(title='修改节设置', prompt='修改本音轨所用乐器:', initialvalue='note.harp') + if not instemp in inst.keys(): + if tkinter.messagebox.askyesno(title='注意', message='您输入的乐器并非游戏内置乐器,是否继续用您输入的字符作为乐器?'): + dataset[0]['musics'][NowMusic]['set']['Instrument'] = instemp + del instemp + break + else: + smsg = '游戏内置乐器如下:请输入英文\n' + for i, j in inst.items(): + smsg += i+' : '+j+'\n' + tkinter.messagebox.showinfo(title='提示', message=smsg) + del smsg + else: + dataset[0]['musics'][NowMusic]['set']['Instrument'] = instemp + del instemp + break + RefreshMusic(NowMusic) + + + def changeFileName(event): + global NowMusic + dataset[0]['musics'][NowMusic]['set']['FileName'] = tkinter.simpledialog.askstring(title='修改节设置', prompt='修改本音轨生成的文件名:', initialvalue='Music') + RefreshMusic(NowMusic) + + + 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) + + + print('按钮点击命令加载完成!') + + print('完成!') + + + print('加载菜单与页面...') + + # 创建一个菜单 + main_menu_bar = tk.Menu(root) + + + # 创建文件菜单 + filemenu = tk.Menu(main_menu_bar, tearoff=0) + + filemenu.add_command(label=u"打开音·创项目...", command=openProject) + filemenu.add_command(label=u"打开旧项目...", command=openOldProject) + filemenu.add_command(label=u"保存项目", command=SaveProject) + filemenu.add_command(label=u"另存为...", command=SaveAsProject) + + filemenu.add_separator() # 分隔符 + + filemenu.add_command(label=u"退出", command=exitapp) + + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=u"文件", menu=filemenu) + + + # 创建编辑菜单 + editmenu = tk.Menu(main_menu_bar, tearoff=0) + editmenu.add_command(label=u"从钢琴MP3导入音轨", command=FromMP3) + editmenu.add_command(label=u"从midi导入音轨", command=FromMidi) + editmenu.add_command(label=u"从文本文件导入音轨", command=FromForm) + editmenu.add_command(label=u"输入音符至音轨", command=FromText) + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=u"编辑", menu=editmenu) + + + + #创建生成函数菜单 + funcmenu = tk.Menu(main_menu_bar, tearoff=0) + funcmenu.add_command(label=u"生成文件至...", command=MakeCMD) + funcmenu.add_command(label=u"生成函数包至...", command=MakeCMDdir) + funcmenu.add_command(label=u"生成附加包文件至...", command=MakePackFile) + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=u"函数(包)", menu=funcmenu) + + + + + #创建生成至世界菜单 + worldmenu = tk.Menu(main_menu_bar, tearoff=0); + worldmenu.add_command(label=u"将音乐以方块存储生成地图", command=ToBlockWorldEpt); + worldmenu.add_command(label=u"将音乐以方块存储载入地图…", command=ToBlockWorld); + worldmenu.add_command(label=u"生成符合当前音乐的函数播放器…", command=MakeFuncPlayer); + worldmenu.add_separator(); + worldmenu.add_command(label=u"将音乐以指令存储生成地图", command=ToCmdWorldEpt); + worldmenu.add_command(label=u"将音乐以指令存储载入地图…", command=ToCmdWorld); + worldmenu.add_command(label=u"将选中音轨以指令存储生成.bdx文件", command=toScbBDXfile) + worldmenu.add_separator(); + worldmenu.add_command(label=u"将音乐以音符盒存储生成地图", command=toRSworldEPT); + worldmenu.add_command(label=u"将音乐以音符盒存储载入地图…", command=toRSworld); + worldmenu.add_separator(); + worldmenu.add_command(label=u"将函数载入世界…", command=func2World); + worldmenu.add_command(label=u"将大函数分割并建立执行链…", command=bigFunc2World); + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=u"世界", menu=worldmenu); + + + + + # 创建生成菜单 + trymenu = tk.Menu(main_menu_bar, tearoff=0) + trymenu.add_command(label=u"展示生成结果", command=ShowCMD) + trymenu.add_command(label=u"建立位于localhost:8080上的websocket服务器播放选中音轨", command=wsPlay) + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=u"实验功能", menu=trymenu) + + + + + + from nmcsup.vers import resetver + + # 创建帮助菜单 + helpmenu = tk.Menu(main_menu_bar, tearoff=0) + helpmenu.add_command(label=u"清除临时文件", command=ClearLog) + helpmenu.add_command(label=u"清除存在文件", command=resetver) + + helpmenu.add_separator() # 分隔符 + + helpmenu.add_command(label=u"帮助", command=apphelp) + helpmenu.add_command(label=u"关于", command=appabout) + helpmenu.add_command(label=u"发送错误日志反馈",command=sendBugReport) + # 将子菜单加入到菜单条中 + main_menu_bar.add_cascade(label=u"帮助与疑问", menu=helpmenu) + + + # 窗口内容 + + UpFrame = tk.Frame(root) + + + UpLeftFrame = tk.Frame(UpFrame, bg='white') + + # 文本 + tk.Label(UpLeftFrame, text='音乐总设置(项目设置)', font=('', 20)).pack() + + LabelPackName = tk.Label(UpLeftFrame, bg='white', text='地图/函数包名: ', font=('', 15)) + LabelMusicTitle = tk.Label(UpLeftFrame, bg='white',text='音乐标题: ', font=('', 15)) + LabelIsRepeat = tk.Label(UpLeftFrame, bg='white', text='是否重复: ', font=('', 15)) + LabelPlayerSelect = tk.Label(UpLeftFrame, bg='white', text='玩家选择器:', 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='重置项目设置', command=ResetSetting).pack() + + + UpLeftFrame.pack(side=tk.LEFT) + + + UpMidleFrame = tk.Frame(UpFrame, bg='blue') + + MusicList_var = tk.StringVar() + ListMusicList = tk.Listbox(UpMidleFrame, listvariable=MusicList_var) + + ListMusicList.bind('', MusicList_selected) # 设置选中响应函数 + + ListMusicList.pack() + + + UpMidleFrame.pack(side=tk.LEFT) + + + UpRightFrame = tk.Frame(UpFrame, bg='white') + + + tk.Label(UpRightFrame, text='当前音轨设置(段落设置)', font=('', 20)).pack() + + LabelEntityName = tk.Label(UpRightFrame, bg='white',text='执行实体名: ', font=('', 15)) + LabelScoreboardName = tk.Label(UpRightFrame, bg='white', text='使用计分板: ', font=('', 15)) + LabelInstrument = tk.Label(UpRightFrame, bg='white',text='所用的乐器: ', font=('', 15)) + LabelFileName = tk.Label(UpRightFrame, bg='white',text='当前音轨名: ', 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='删除选中音轨', command=DelNowMusic).pack() + + + UpRightFrame.pack(side=tk.LEFT) + + + UpFrame.pack() + + + DownFrame = tk.Frame(root, bg='blue') + + + # 音符列表菜单 + NoteList_var = tk.StringVar() + ListNoteList = tk.Listbox(DownFrame, listvariable=NoteList_var, width=40, height=30) + + ListNoteList.bind('', NoteList_selected) # 设置选中响应函数 + + ListNoteList.pack(side=tk.LEFT) + + + # 指令列表菜单 + ListCMDList = tk.Text(DownFrame) + + ListCMDList.pack(side=tk.RIGHT) + + DownFrame.pack() + + + RefreshMain() + + + # 将菜单添加到主窗口中 + root.config(menu=main_menu_bar) + + print('完成!') + + + log("启动root.mainloop(窗口)") + + # 进入窗口消息循环 + root.mainloop() + + del filemenu, editmenu, helpmenu + + exitapp() + + +if __name__ == '__main__': + __main__(); + +