From 54229f40e9c1cffa28a53a8116e74ddc2e873759 Mon Sep 17 00:00:00 2001 From: Shinrin Ouja Moriking Date: Sat, 5 Aug 2023 11:23:04 -0600 Subject: [PATCH] GUI for pms2bemani --- pms2bemani/README.md | 10 + pms2bemani/pms2bemani/gui_assets/banner.png | Bin 0 -> 2146 bytes pms2bemani/pms2bemani/gui_assets/bg.png | Bin 0 -> 3108 bytes .../pms2bemani/gui_assets/chara_list.txt | 2363 +++++++++++++++++ pms2bemani/pms2bemani/gui_assets/config.json | 1 + .../gui_assets/gui_translation.json | 59 + pms2bemani/pms2bemani/gui_assets/hariai.png | Bin 0 -> 6140 bytes pms2bemani/pms2bemani/gui_assets/logo.ico | Bin 0 -> 4958 bytes pms2bemani/pms2bemani/gui_assets/logo.png | Bin 0 -> 1978 bytes .../pms2bemani/gui_assets/metadata.json | 98 + pms2bemani/pms2bemani/pms2bemaniGUI.py | 951 +++++++ pms2bemani/pms2bemani/requirements.txt | 5 +- 12 files changed, 3486 insertions(+), 1 deletion(-) create mode 100644 pms2bemani/pms2bemani/gui_assets/banner.png create mode 100644 pms2bemani/pms2bemani/gui_assets/bg.png create mode 100644 pms2bemani/pms2bemani/gui_assets/chara_list.txt create mode 100644 pms2bemani/pms2bemani/gui_assets/config.json create mode 100644 pms2bemani/pms2bemani/gui_assets/gui_translation.json create mode 100644 pms2bemani/pms2bemani/gui_assets/hariai.png create mode 100644 pms2bemani/pms2bemani/gui_assets/logo.ico create mode 100644 pms2bemani/pms2bemani/gui_assets/logo.png create mode 100644 pms2bemani/pms2bemani/gui_assets/metadata.json create mode 100644 pms2bemani/pms2bemani/pms2bemaniGUI.py diff --git a/pms2bemani/README.md b/pms2bemani/README.md index b28307f..16e7fc6 100644 --- a/pms2bemani/README.md +++ b/pms2bemani/README.md @@ -77,6 +77,16 @@ required arguments: Example: `python3 pms2bemani.py --input-np wonderingbeats/01_kouunn-n.pms --input-hp wonderingbeats/02_kouunn-h.pms --input-op wonderingbeats/03_kouunn-ex.pms --keysounds-folder wonderingbeats --name wonderingbeats_convert --new --preview-offset 10.4 --preview-duration 15` +## GUI for pms2bemani + +GUI and manager for generate mods from p2b files. +Based on the fields filled, makes a subprocess call to pms2bemani.py with arguments. +This script needs to be in the same folder as pms2bemani.py and gui_stuff. + +p2b files: +JSON file with attributes related to pms2bemani.py + + ## Credits - ifstools (https://github.com/mon/ifstools) - 2dxTools (https://github.com/mon/2dxTools) diff --git a/pms2bemani/pms2bemani/gui_assets/banner.png b/pms2bemani/pms2bemani/gui_assets/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..abd993d01e72fe816e83a940501618550933d1ee GIT binary patch literal 2146 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 T6D}rt8UXfoaN8Q28xQ^gHdH;y literal 0 HcmV?d00001 diff --git a/pms2bemani/pms2bemani/gui_assets/bg.png b/pms2bemani/pms2bemani/gui_assets/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..8d81f30a2f17509a0e6026c81c5b6864b8c9f09e GIT binary patch literal 3108 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 KnG-JGdh|b-A!sQ8 literal 0 HcmV?d00001 diff --git a/pms2bemani/pms2bemani/gui_assets/logo.ico b/pms2bemani/pms2bemani/gui_assets/logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..fc82e8fbabd96381b440565fb46b42d4812d5ce3 GIT binary patch literal 4958 zcmeI0F-|Kn6h)0v{w4zH*A^9Jmf(VdGE2x3vIOsdCCn07!i0)4OBi+l3qUgG4zc9# zZyQCz0|hs_dG>wwdv`pODPqh8pX+PGw>5WH#{4zL+(0CA3#AL|OJlD7d~g;%zSc^? zBMfkY7WRUAjZnQ5WB(Yx+lRxGD1VWA#=W50v5%rV(GtZM81s&CjtzopJirl7Fs@Id za-xS0=GY>n>n(FJLVfN}^u!$$v~Pmx-gCyfKGj`A2R$6%2vxfTi7>e0fEWRJe3nyz8wenB7m zhL3SUAHLyZTF{5izJ}6$?4{}KYv|RpRM*!`pdVprPY-Vzc@78h6HEc=r zxCf=0dUw}gNtE{V&}tr}JJ_RVsivh@4W2}4PY=!2OrQ@7`tS`O0fg@u2bJ^XgUcDTFsgp2bj#?>gj&bM4)Ecca~c z5k-_4QP8jv1Yf+wL@*@c2pUw3U~noR7y^OAlW7aVu7yfe9d7r}5Jz8L)fgpK>){%v5+%yqEhJPW4 z8_b4K4JWE`8!xE>uqERfL?cLPc~axWW?-TMXp$8Vc5VLw43#Ahw!jf0Lz)jnf36=Vq3H5may_Nv^2>Qi-q zx@;6Kk|c?`+%}$dF_hq*gVH2T5u_V_agyX17ss$@`h!6^U5apZ{;ISXyz*dC)6_VE zNF)-r1Y=Y6CW3OiApuR$G!7BC(W;ny5?73A0}Os(h`OwqvZ|mKBQK~erU!#o`(ub} z8Cu0i=Lu$vNb(v%*+?s<6i^Z~IITsGrNkwX05K2;ifKSBmBDIJ)l`kBdK>D@<68t^ zZbPAr#*kj(@r;CFRxX2Kq!ThE+6cF5fT#n8+M~_xKyaft-M&eEWj$ldTBB~zeVZd^nZvup-G+}5ajhs)7sX7#f?wFK|P>2gE zhRG`;2>Lx3jM*m35*Kj+7c06++#$GGT%_%8+|7#;E;*bmX=h!ulX48~_p4%yRat9) zf0s+D2s!>yr5U>fSiyx$6azCN+MT!{vLsGP5tihgf}M;A18fiJGJMha*kD%6m1Mbc zvJsl09XQQ8Mcm=C3pfuV0xqzkV7D{0L^>#|n^O(K1!M!3t~LFB)Pu*%iLtb9cw)B5r5i;FsOO`dyW> z-_v00LpJ08v7Szg80D2F04FDbS-}w2i0Lm1@$Y)2o(&pD18_LwtYv1p!i&s&1`4Fs z;q;wg^qoMEtj?g{8*W(Dy@9GbNETEsU6I|ByP^2)t$AnAGw2lGp)t#IdV1(h$f9?q zPuU!*?!1^om5{5X20|ZO;_Z9=RMEBMM}JOVxaXpGVaIRYlEvBK%lWIn%?V@`?p$)Y zIoCU{@#@N#=hh56lU?8Vgzm-CUiZ%*Da(a+JfeCdmATlQaBw+PP{-r{3LlZx|wJCCe+`05i^bkM!+`2B}F zO?zPKODik5Nf)P0J#?w6c=YKtS08I$+;Ah1Rk}BJs;uq%++o^ZHz$8mSP|+-E?qi1 z@408IW}T}#Tfrr|%g22;zH9i|r(8c2bsg;9`e5J9(c?ZY)Gl1#rS+be_(8|=VWWPZ zvb*Nq{gZhoGPU literal 0 HcmV?d00001 diff --git a/pms2bemani/pms2bemani/gui_assets/metadata.json b/pms2bemani/pms2bemani/gui_assets/metadata.json new file mode 100644 index 0000000..8f3891b --- /dev/null +++ b/pms2bemani/pms2bemani/gui_assets/metadata.json @@ -0,0 +1,98 @@ +{ + "category":{ + "c1":{ + "text":"beatmania", + "value": 1 + }, + "c2":{ + "text":"IIDX", + "value": 2 + }, + "c3":{ + "text":"DDR", + "value": 4 + }, + "c4":{ + "text":"Gitadora", + "value": 8 + }, + "c5":{ + "text":"Mambo a Go Go", + "value": 16 + }, + "c6":{ + "text":"pop'n stage", + "value": 32 + }, + "c7":{ + "text":"Keyboarmania", + "value": 64 + }, + "c8":{ + "text":"Dance Maniax", + "value": 128 + }, + "c9":{ + "text":"bmIII", + "value": 256 + }, + "c10":{ + "text":"Toy's March", + "value": 512 + }, + "c11":{ + "text":"ee'mall", + "value": 1024 + }, + "c12":{ + "text":"jubeat", + "value": 2048 + }, + "c13":{ + "text":"Reflec Beat", + "value": 4096 + }, + "c14":{ + "text":"SDVX", + "value": 8192 + }, + "c15":{ + "text":"BeatStream", + "value": 16384 + }, + "c16":{ + "text":"Nostalgia", + "value": 32768 + } + }, + "mask":{ + "m1":{ + "text":"Display a fake BPM", + "value": 8 + }, + "m3":{ + "text":"TV/J-Pop category", + "value": 65536 + }, + "m4":{ + "text":"Easy chart flag", + "value": 524288 + }, + "m5":{ + "text":"Hyper chart flag", + "value": 16777216 + }, + "m6":{ + "text":"Ex chart flag", + "value": 33554432 + }, + "m7":{ + "text":"Battle hyper chart flag", + "value": 67108864 + }, + "m9":{ + "text":"Default for placeholder songs", + "value": 2147483648 + } + } +} diff --git a/pms2bemani/pms2bemani/pms2bemaniGUI.py b/pms2bemani/pms2bemani/pms2bemaniGUI.py new file mode 100644 index 0000000..fd34ccb --- /dev/null +++ b/pms2bemani/pms2bemani/pms2bemaniGUI.py @@ -0,0 +1,951 @@ +import tkinter +from tkinter import * +import json +import os +import jaconv +import subprocess +import re +from tkinter import filedialog as fd +from tkinter import messagebox +from tkinter.messagebox import showinfo,askyesno +from PIL import ImageTk,ImageDraw,Image + +class Application(tkinter.Frame): + def __init__(self, parent): + super().__init__(parent) + self.current_file = '' + #load translation + translation_file = open('gui_assets/gui_translation.json') + translation_data = json.load(translation_file) + self.tr = translation_data["languages"][translation_data["selected"]] + translation_file.close() + #style + parent.title("Pms2bemani") + parent.protocol("WM_DELETE_WINDOW",lambda: self.delete_window(parent)) + # Setting icon + logo_img = PhotoImage(file ='gui_assets/logo.png') + parent.iconphoto(False, logo_img) + #load category data + self.l = self.chara_txt_to_data() + + #grids + for i in range(38): + parent.columnconfigure(i, weight=10) + + #load masks + mask_file = open('gui_assets/metadata.json') + metadata = json.load(mask_file) + mask_data = metadata["mask"] + category_data = metadata["category"] + mask_file.close() + #masks array + #get texts + self.mask_des = [] + self.mask_value = [] + for key in mask_data: + self.mask_des.append(mask_data[key]["text"]) + self.mask_value.append(mask_data[key]["value"]) + self.vars_mask = [] + for label, value in zip(self.mask_des, self.mask_value): + var = tkinter.IntVar(value=0) + self.vars_mask.append(var) + #category array + #get texts + self.category_des = [] + self.category_value = [] + for key in category_data: + self.category_des.append(category_data[key]["text"]) + self.category_value.append(category_data[key]["value"]) + self.vars_category = [] + for label, value in zip(self.category_des, self.category_value): + var = tkinter.IntVar(value=0) + self.vars_category.append(var) + + #check buttons vars + self.has_battle_var = BooleanVar() + self.is_jacket_var = BooleanVar() + self.new_chart_format = BooleanVar() + + # first menu + self.menu_bar= tkinter.Menu(parent) + self.menu_file = tkinter.Menu(self.menu_bar, tearoff=False) + self.menu_file.add_command(label="New",command=lambda:self.new_fields(parent)) + self.menu_file.add_command(label="Open",command=lambda:self.open_p2b(parent)) + self.menu_file.add_command(label="Save",command=lambda:self.save()) + self.menu_file.add_command(label="Save As..",command=lambda:self.save_as(parent)) + self.menu_file.entryconfig(2, state=DISABLED) + # Add options to menu. + self.menu_bar.add_cascade(menu=self.menu_file, label=self.tr["File"]) + self.menu_bar.add_cascade(label=self.tr["Options"],command=lambda:self.options(parent)) + parent.config(menu=self.menu_bar) + #create window widgets + self.create_widgets(parent) + + + def create_widgets(self,parent): + #Mod data + self.tag_mod_data = tkinter.Label(parent, text=self.tr["Mod data"]) + self.tag_mod_data.grid(column=0, row=0,pady = 2,sticky='ew') + #Name + self.tag_name = tkinter.Label(parent, text=self.tr["Name"]) + self.tag_name.grid(column=0, row=1,sticky="W",pady = 2) + self.box_name = tkinter.Entry(parent) + self.box_name.grid(column=1, row=1,sticky='ew') + #Music ID + vcmd = (self.register(self.callback)) + self.tag_music_id = tkinter.Label(parent, text=self.tr["Music ID"]) + self.tag_music_id.grid(column=0, row=2,sticky="W",pady = 2) + self.box_music_id = tkinter.Entry(parent, validate='all', validatecommand=(vcmd, '%P')) + self.box_music_id.grid(column=1, row=2,sticky='ew') + #Keysounds folder + self.tag_keysounds = tkinter.Label(parent, text=self.tr["Keysounds folder"]) + self.tag_keysounds.grid(column=0, row=3,sticky="W",pady = 2) + self.box_keysounds = tkinter.Entry(parent) + self.box_keysounds.grid(column=1, row=3,sticky='ew') + self.find_keysounds = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.select_directory(self.box_keysounds)) + self.find_keysounds.grid(column=2, row=3,sticky="W") + + + #Charts title + self.tag_charts_title = tkinter.Label(parent, text=self.tr["Charts"]) + self.tag_charts_title.grid(column=0, row=5,pady = 2,sticky='ew') + #battle mode stuff + self.tag_input_bp = tkinter.Label(parent, text=self.tr["Battle Mode File"]) + self.tag_input_bp.grid(column=0, row=6,sticky="W",pady = 2) + self.box_input_bp = tkinter.Entry(parent) + self.box_input_bp.grid(column=1, row=6,sticky='ew') + self.find_input_bp = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.select_file_pms(self.box_input_bp)) + self.find_input_bp.grid(column=2, row=6,sticky="W") + #Easy difficulty + self.tag_input_ep = tkinter.Label(parent, text=self.tr["Easy Chart File"]) + self.tag_input_ep.grid(column=0, row=7,sticky="W",pady = 2) + self.box_input_ep = tkinter.Entry(parent) + self.box_input_ep.grid(column=1, row=7,sticky='ew') + self.find_input_ep = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.select_file_pms(self.box_input_ep)) + self.find_input_ep.grid(column=2, row=7,sticky="W") + #Normal difficulty + self.tag_input_np = tkinter.Label(parent, text=self.tr["Normal Chart File"]) + self.tag_input_np.grid(column=0, row=8,sticky="W",pady = 2) + self.box_input_np = tkinter.Entry(parent) + self.box_input_np.grid(column=1, row=8,sticky='ew') + self.find_input_np = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.select_file_pms(self.box_input_np)) + self.find_input_np.grid(column=2, row=8,sticky="W") + #Hyper difficulty + self.tag_input_hp = tkinter.Label(parent, text=self.tr["Hyper Chart File"]) + self.tag_input_hp.grid(column=0, row=9,sticky="W",pady = 2) + self.box_input_hp = tkinter.Entry(parent) + self.box_input_hp.grid(column=1, row=9,sticky='ew') + self.find_input_hp = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.select_file_pms(self.box_input_hp)) + self.find_input_hp.grid(column=2, row=9,sticky="W") + #Ex difficulty + self.tag_input_op = tkinter.Label(parent, text=self.tr["Ex Chart File"]) + self.tag_input_op.grid(column=0, row=10,sticky="W",pady = 2) + self.box_input_op = tkinter.Entry(parent) + self.box_input_op.grid(column=1, row=10,sticky='ew') + self.find_input_op = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.select_file_pms(self.box_input_op)) + self.find_input_op.grid(column=2, row=10,sticky="W") + #Metadata + self.tag_metadata = tkinter.Label(parent, text=self.tr["Metadata"]) + self.tag_metadata.grid(column=0, row=11,pady = 2,sticky='ew') + #FW title + self.tag_fw_title = tkinter.Label(parent, text=self.tr["FW title"]) + self.tag_fw_title.grid(column=0, row=12,sticky="W",pady = 2) + self.box_fw_title = tkinter.Entry(parent) + self.box_fw_title.grid(column=1, row=12,sticky='ew') + self.btn_fw_title = tkinter.Button(parent,text=self.tr["FW"],command=lambda: self.half2full(self.box_fw_title,self.box_fw_title )) + self.btn_fw_title.grid(column=2, row=12,sticky="W") + #FW artist + self.tag_fw_artist = tkinter.Label(parent, text=self.tr["FW artist"]) + self.tag_fw_artist.grid(column=0, row=13,sticky="W",pady = 2) + self.box_fw_artist = tkinter.Entry(parent) + self.box_fw_artist.grid(column=1, row=13,sticky='ew') + self.btn_fw_artist = tkinter.Button(parent,text=self.tr["FW"],command=lambda: self.half2full(self.box_fw_artist,self.box_fw_artist )) + self.btn_fw_artist.grid(column=2, row=13,sticky="W") + #FW genre + self.tag_fw_genre = tkinter.Label(parent, text=self.tr["FW genre"]) + self.tag_fw_genre.grid(column=0, row=14,sticky="W",pady = 2) + self.box_fw_genre = tkinter.Entry(parent) + self.box_fw_genre.grid(column=1, row=14,sticky='ew') + self.btn_fw_genre = tkinter.Button(parent,text=self.tr["FW"],command=lambda: self.half2full(self.box_fw_genre,self.box_fw_genre )) + self.btn_fw_genre.grid(column=2, row=14,sticky="W") + #Title + self.tag_title = tkinter.Label(parent, text=self.tr["Title"]) + self.tag_title.grid(column=0, row=15,sticky="W",pady = 2) + self.box_title = tkinter.Entry(parent) + self.box_title.grid(column=1, row=15,sticky='ew') + #Artist + self.tag_artist = tkinter.Label(parent, text=self.tr["Artist"]) + self.tag_artist.grid(column=0, row=16,sticky="W",pady = 2) + self.box_artist = tkinter.Entry(parent) + self.box_artist.grid(column=1, row=16,sticky='ew') + #Genre + self.tag_genre = tkinter.Label(parent, text=self.tr["Genre"]) + self.tag_genre.grid(column=0, row=17,sticky="W",pady = 2) + self.box_genre = tkinter.Entry(parent) + self.box_genre.grid(column=1, row=17,sticky='ew') + #Chara 1 + self.tag_chara_1 = tkinter.Label(parent, text=self.tr["Chara 1"]) + self.tag_chara_1.grid(column=0, row=18,sticky="W",pady = 2) + self.box_chara_1 = tkinter.Entry(parent) + self.box_chara_1.grid(column=1, row=18,sticky='ew') + self.sel_chara_1 = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.chara_selection(parent,self.box_chara_1)) + self.sel_chara_1.grid(column=2, row=18,sticky="W") + #Chara 2 + self.tag_chara_2 = tkinter.Label(parent, text=self.tr["Chara 2"]) + self.tag_chara_2.grid(column=0, row=19,sticky="W",pady = 2) + self.box_chara_2 = tkinter.Entry(parent) + self.box_chara_2.grid(column=1, row=19,sticky='ew') + self.sel_chara_2 = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.chara_selection(parent,self.box_chara_2)) + self.sel_chara_2.grid(column=2, row=19,sticky="W") + #Has battle hyper + self.tag_battle_hyper = tkinter.Label(parent, text=self.tr["Has battle hyper"]) + self.tag_battle_hyper.grid(column=0, row=20,sticky="W",pady = 2) + self.check_battle_hyper = tkinter.Checkbutton(parent,onvalue=True, offvalue=False,variable=self.has_battle_var) + self.check_battle_hyper.grid(column=1, row=20,sticky="W",pady = 2) + #Hariai is jacket + self.tag_is_jacket = tkinter.Label(parent, text=self.tr["Hariai is jacket"]) + self.tag_is_jacket.grid(column=0, row=21,sticky="W",pady = 2) + self.check_is_jacket = tkinter.Checkbutton(parent,onvalue=True, offvalue=False,variable=self.is_jacket_var) + self.check_is_jacket.grid(column=1, row=21,sticky="W",pady = 2) + + #Folder (version) + self.tag_version = tkinter.Label(parent, text=self.tr["Folder"]) + self.tag_version.grid(column=0, row=22,sticky="W",pady = 2) + # Create the list of pop'n music versions + self.versions = [] + [self.versions.append(x+1) for x in range(27)] + # Variable to keep track of the option + # selected in OptionMenu + self.value_inside_folder = tkinter.StringVar(parent) + # Set the default value of the variable + self.value_inside_folder.set(None) + # Create the option menu widget and passing + # the options_list and value_inside to it. + self.question_menu_folder = tkinter.OptionMenu(parent, self.value_inside_folder, *self.versions) + self.question_menu_folder.grid(column=1, row=22,sticky="EW") + #clean options + self.clean_folder = tkinter.Button(parent,text=self.tr["Clean"],command=lambda: self.clean_value(self.value_inside_folder)) + self.clean_folder.grid(column=2, row=22,sticky="W") + + #Category + self.tag_category = tkinter.Label(parent, text=self.tr["Categories"]) + self.tag_category.grid(column=0, row=23,sticky="W",pady = 2) + self.create_category = tkinter.Button(parent,text=self.tr["Open"],command=lambda:self.optionWindow(parent,self.category_des,self.category_value,self.vars_category,self.tr["Categories"])) + self.create_category.grid(column=1, row=23,sticky="W",pady = 2) + + + #CS Version + self.tag_cs = tkinter.Label(parent, text=self.tr["CS Version"]) + self.tag_cs.grid(column=0, row=24,sticky="W",pady = 2) + #Category list menu + # Variable to keep track of the option + # selected in OptionMenu + self.value_inside_cs = tkinter.StringVar(parent) + # Set the default value of the variable + self.value_inside_cs.set(None) + # Create the option menu widget and passing + # the options_list and value_inside to it. + self.cs_versions = [] + [self.cs_versions.append(x+1) for x in range(1)] + self.question_menu_cs = tkinter.OptionMenu(parent, self.value_inside_cs, *self.cs_versions) + self.question_menu_cs.grid(column=1, row=24,sticky="EW") + #clean options + self.clean_cs = tkinter.Button(parent,text=self.tr["Clean"],command=lambda: self.clean_value(self.value_inside_cs)) + self.clean_cs.grid(column=2, row=24,sticky="W") + + #Mask + self.tag_mask = tkinter.Label(parent, text=self.tr["Mask"]) + self.tag_mask.grid(column=0, row=25,sticky="W",pady = 2) + #Mask subwindow + self.create_mask = tkinter.Button(parent,text=self.tr["Open"],command=lambda:self.optionWindow(parent,self.mask_des,self.mask_value,self.vars_mask,self.tr["Mask"])) + self.create_mask.grid(column=1, row=25,sticky="W",pady = 2) + + + #Chara X + self.tag_chara_position_x = tkinter.Label(parent, text=self.tr["Chara position X"]) + self.tag_chara_position_x.grid(column=0, row=26,sticky="W",pady = 2) + self.box_chara_position_x = tkinter.Spinbox(from_=0,to=2000,increment=1,validate='all', validatecommand=(vcmd, '%P')) + self.box_chara_position_x.grid(column=1, row=26) + #Chara Y + self.tag_chara_position_y = tkinter.Label(parent, text=self.tr["Chara position Y"]) + self.tag_chara_position_y.grid(column=0, row=27,sticky="W",pady = 2) + self.box_chara_position_y = tkinter.Spinbox(from_=0,to=2000,increment=1,validate='all', validatecommand=(vcmd, '%P')) + self.box_chara_position_y.grid(column=1, row=27) + + #Preview + self.tag_preview = tkinter.Label(parent, text=self.tr["Preview"]) + self.tag_preview.grid(column=0, row=28,pady = 2,sticky='ew') + + #Preview File + self.tag_preview_file = tkinter.Label(parent, text=self.tr["Preview file"]) + self.tag_preview_file.grid(column=0, row=29,sticky="W",pady = 2) + self.box_preview_file = tkinter.Entry(parent) + self.box_preview_file.grid(column=1, row=29,sticky='ew') + self.find_preview_file = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.select_file_sound(self.box_preview_file)) + self.find_preview_file.grid(column=2, row=29,sticky="W") + + #Preview offset + self.tag_preview_offset = tkinter.Label(parent, text=self.tr["Preview offset"]) + self.tag_preview_offset.grid(column=0, row=30,sticky="W",pady = 2) + self.box_preview_offset = tkinter.Spinbox(from_=0,to=2000,increment=1,validate='all', validatecommand=(vcmd, '%P')) + self.box_preview_offset.grid(column=1, row=30) + + #Preview duration + self.tag_preview_duration = tkinter.Label(parent, text=self.tr["Preview duration"]) + self.tag_preview_duration.grid(column=0, row=31,sticky="W",pady = 2) + self.box_preview_duration = tkinter.Spinbox(from_=0,to=2000,increment=1,validate='all', validatecommand=(vcmd, '%P')) + self.box_preview_duration.grid(column=1, row=31) + + #Extra + self.tag_extra = tkinter.Label(parent, text=self.tr["Extra"]) + self.tag_extra.grid(column=5, row=21,pady = 2,sticky='ew') + + #New chart format + self.tag_new_format = tkinter.Label(parent, text=self.tr["New chart format"]) + self.tag_new_format.grid(column=5, row=22,sticky="W",pady = 2) + self.check_new_format = tkinter.Checkbutton(parent,onvalue=True, offvalue=False,variable=self.new_chart_format) + self.check_new_format.grid(column=6, row=22,sticky="W",pady = 2) + + #Banner + self.tag_banner = tkinter.Label(parent, text=self.tr["Banner"]) + self.tag_banner.grid(column=5, row=23,sticky="W",pady = 2) + self.box_banner = tkinter.Entry(parent) + self.box_banner.grid(column=6, row=23,sticky='ew') + self.find_banner = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.select_file_image(self.box_banner,parent,"banner")) + self.find_banner.grid(column=7, row=23,sticky="W") + self.clean_banner = tkinter.Button(parent,text=self.tr["Clean"],command=lambda: self.clean_image(parent,"banner",self.box_banner)) + self.clean_banner.grid(column=8, row=23,sticky="w",columnspan=1) + + #Background + empty = tkinter.Label(parent) + empty.grid(column=4, row=22,sticky="W") + self.tag_background = tkinter.Label(parent, text=self.tr["Background"]) + self.tag_background.grid(column=5, row=24,sticky="W",pady = 2) + self.box_background = tkinter.Entry(parent) + self.box_background.grid(column=6, row=24,sticky='ew') + self.find_background = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.select_file_image(self.box_background,parent,"bg")) + self.find_background.grid(column=7, row=24,sticky="W") + self.clean_background = tkinter.Button(parent,text=self.tr["Clean"],command=lambda: self.clean_image(parent,"bg",self.box_background)) + self.clean_background.grid(column=8, row=24,sticky="w") + + #Hariai + self.tag_hariai = tkinter.Label(parent, text=self.tr["Hariai"]) + self.tag_hariai.grid(column=5, row=25,sticky="W",pady = 2) + self.box_hariai = tkinter.Entry(parent) + self.box_hariai.grid(column=6, row=25,sticky='ew') + self.find_hariai = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.select_file_image(self.box_hariai,parent,"hariai")) + self.find_hariai.grid(column=7, row=25,sticky="W") + self.clean_hariai = tkinter.Button(parent,text=self.tr["Clean"],command=lambda: self.clean_image(parent,"hariai",self.box_hariai)) + self.clean_hariai.grid(column=8, row=25,sticky="w",columnspan=1) + + + #Output folder + self.tag_output = tkinter.Label(parent, text=self.tr["Output folder"]) + self.tag_output.grid(column=5, row=26,sticky="W",pady = 2) + self.box_output= tkinter.Entry(parent) + self.box_output.grid(column=6, row=26,sticky='ew') + self.find_output = tkinter.Button(parent,text=self.tr["Open"],command=lambda: self.select_directory(self.box_output)) + self.find_output.grid(column=7, row=26,sticky="W") + + #Create Mod + self.create_mod = tkinter.Button(parent,text=self.tr["Create Mod"],command=lambda:self.generate_mod()) + self.create_mod.grid(column=6, row=28,sticky="EW") + + #Banner display + self.tag_image_banner=tkinter.Label(parent, text=self.tr["Banner"]) + self.tag_image_banner.grid(column=6, row=0,sticky="E",pady = 2) + self.clean_image(parent,"banner",self.box_banner) + + #Bg display + self.tag_image_bg=tkinter.Label(parent, text=self.tr["Background"]) + self.tag_image_bg.grid(column=7, row=4,sticky="EW",pady = 10) + self.clean_image(parent,"bg",self.box_background) + + + #Hariai display + self.tag_image_hariai = tkinter.Label(parent, text=self.tr["Hariai"]) + self.tag_image_hariai.grid(column=6, row=4,sticky="W",pady = 3) + self.clean_image(parent,"hariai",self.box_hariai) + + + def box_to_param(self,param,widget): + if ((widget.get() != '') and (widget.get() != 'None')): + self.params.append(param) + self.params.append(widget.get()) + + def num_box_to_param(self,param,widget): + if ((widget.get() != '') and (widget.get() != '0')): + self.params.append(param) + self.params.append(widget.get()) + + def bool_to_param(self,param,widget): + if widget.get(): + self.params.append(param) + + def bitfields_to_param(self,param,variables): + values = [var.get() for var in variables] + result = sum(values) + if result > 0: + self.params.append(param) + self.params.append(str(result)) + #get data for our file + + def generate_mod(self): + self.params = [] + #get config stuff for our command + options = self.load_config_file() + if options["command"] != '': + self.params.append(options["command"]) + else: + self.params.append("python") + + self.params.append('pms2bemani.py') + #Create command based on our fields + self.box_to_param("--name",self.box_name) + self.box_to_param("--musicid",self.box_music_id) + self.box_to_param("--keysounds-folder",self.box_keysounds) + self.box_to_param("--banner",self.box_banner) + self.box_to_param("--input-bp",self.box_input_bp) + self.box_to_param("--input-ep",self.box_input_ep) + self.box_to_param("--input-np",self.box_input_np) + self.box_to_param("--input-hp",self.box_input_hp) + self.box_to_param("--input-op",self.box_input_op) + self.box_to_param("--metadata-fw-title",self.box_fw_title) + self.box_to_param("--metadata-fw-artist",self.box_fw_artist) + self.box_to_param("--metadata-fw-genre",self.box_fw_genre) + self.box_to_param("--metadata-title",self.box_title) + self.box_to_param("--metadata-artist",self.box_artist) + self.box_to_param("--metadata-genre",self.box_genre) + self.box_to_param("--metadata-chara1",self.box_chara_1) + self.box_to_param("--metadata-chara2",self.box_chara_2) + self.bool_to_param("--metadata-has-battle-hyper",self.has_battle_var) + self.bool_to_param("--metadata-hariai-is-jacket",self.is_jacket_var) + self.box_to_param("--metadata-folder",self.value_inside_folder) + self.bitfields_to_param("--metadata-categories",self.vars_category) + self.box_to_param("--metadata-cs-version",self.value_inside_cs) + self.bitfields_to_param("--metadata-mask",self.vars_mask) + self.num_box_to_param("--metadata-chara-x",self.box_chara_position_x) + self.num_box_to_param("--metadata-chara-y",self.box_chara_position_y) + self.box_to_param("--preview",self.box_preview_file) + self.num_box_to_param("--preview-offset",self.box_preview_offset) + self.num_box_to_param("--preview-duration",self.box_preview_duration) + self.bool_to_param("--new",self.new_chart_format) + self.box_to_param("--bg",self.box_background) + self.box_to_param("--hariai",self.box_hariai) + self.box_to_param("--output",self.box_output) + subprocess.call(self.params) + print("==========PROCESS COMPLETED==========") + + #Function that create subwindows for bitfield forms + def optionWindow(self,parent,descriptions,values,array,title): + + # Toplevel object which will + # be treated as a new window + ctWin = Toplevel(parent) + # sets the title of the + # Toplevel widget + ctWin.title(title) + # sets the geometry of toplevel + ctWin.geometry("400x400") + for i in range(14): + ctWin.columnconfigure(i, weight=3) + #generate check buttons + count = 0 + for label, value in zip(descriptions, values): + cb = tkinter.Checkbutton(ctWin, text=label, onvalue=value, offvalue=0, variable=array[count]) + cb.grid(column=0, row=count,sticky="W") + cb.var = array[count] + count = count + 1 + + ctWin.transient(parent) + ctWin.grab_set() + parent.wait_window(ctWin) + + #validations + #validate int entrys + def callback(self, P): + if str.isdigit(P) or P == "": + return True + else: + return False + + def select_directory(self,widget): + folder = fd.askdirectory() + if folder == '': + return + widget.delete(0,"end") + widget.insert(0,folder) + + def select_file_image(self,widget,parent,type): + filetypes = ( + ('PNG file', '*.png'), + ('All files', '*.*') + ) + filename = fd.askopenfilename( + title='Open a file', + #save folder + initialdir = "/áéá", + filetypes=filetypes) + #validate is a png + if filename == '': + return + if filename.endswith('.png'): + self.insert_image(parent,filename,widget,type) + + + def insert_image(self,parent,filename,widget,type): + my_image=Image.open(filename) + banner = ImageTk.PhotoImage(my_image) + + if type == "banner" and my_image.size == (244,58): + self.tag_image_banner = tkinter.Label(parent,image=banner) + self.tag_image_banner.image = banner + self.tag_image_banner.grid(column=6, row=0,sticky="W",pady = 2,rowspan=4,columnspan=3) + elif type == "bg" and my_image.size == (128, 256): + self.tag_image_bg = tkinter.Label(parent,image=banner) + self.tag_image_bg.image = banner + self.tag_image_bg.grid(column=7, row=4,sticky="W",pady = 2,rowspan=13,columnspan=2) + elif type == "hariai" and ((my_image.size == (250, 322)) or (my_image.size == (382, 502))): + if((my_image.size == (382, 502))): + my_image = my_image.resize((250, 322)) + banner = ImageTk.PhotoImage(my_image) + self.tag_image_hariai = tkinter.Label(parent,image=banner) + self.tag_image_hariai.image = banner + self.tag_image_hariai.grid(column=4, row=5,sticky="W",pady = 2,rowspan=13,columnspan=3) + else: + tkinter.messagebox.showerror(title="Error", message=self.tr["Image error"]) + return 0 + widget.delete(0,"end") + widget.insert(0,filename) + + + + def clean_image(self,parent,type,widget): + if type == "bg": + image=Image.open('gui_assets/bg.png') + image_ui = ImageTk.PhotoImage(image) + self.tag_image_bg = tkinter.Label(parent,image=image_ui) + self.tag_image_bg.image = image_ui + self.tag_image_bg.grid(column=7, row=4,sticky="W",pady = 2,rowspan=13,columnspan=2) + widget.delete(0,"end") + elif type == "banner": + image=Image.open('gui_assets/banner.png') + image_ui = ImageTk.PhotoImage(image) + self.tag_image_banner=tkinter.Label(parent,image=image_ui) + self.tag_image_banner.image = image_ui + self.tag_image_banner.grid(column=6, row=0,sticky="W",pady = 2,rowspan=4,columnspan=3) + widget.delete(0,"end") + elif type == "hariai": + image=Image.open('gui_assets/hariai.png') + image_ui = ImageTk.PhotoImage(image) + self.tag_image_hariai=tkinter.Label(parent,image=image_ui) + self.tag_image_hariai.image = image_ui + self.tag_image_hariai.grid(column=4, row=5,sticky="W",pady = 2,rowspan=13,columnspan=3) + widget.delete(0,"end") + + def select_file_pms(self,widget): + filetypes = ( + ('Pms files', '*.pms'), + ('All files', '*.*') + ) + filename = fd.askopenfilename( + title='Open a file', + #save folder + initialdir = "/áéá", + filetypes=filetypes) + if filename == '': + return + widget.delete(0,"end") + widget.insert(0,filename) + + def select_file_sound(self,widget): + filetypes = ( + ('OGG', '*.ogg'), + ('Waveform Audio Format', '*.wav'), + ('All files', '*.*') + ) + filename = fd.askopenfilename( + title='Open a file', + #save folder + initialdir = "/áéá", + filetypes=filetypes) + if filename == '': + return + widget.delete(0,"end") + widget.insert(0,filename) + + def clean_value(self,widget): + widget.set(None) + + def change_language(self,language): + translation_file = open('gui_assets/gui_translation.json') + translation_data = json.load(translation_file) + self.tr = translation_data["languages"][language] + self.tag_input_bp['text'] = self.tr["Battle Mode File"] + translation_file.close() + + + def half2full(self,widget,widget2): + text = widget.get() + #regex for FW fields + if re.match("^[A-Za-za-zA-Z0-90-9゠-ヿ_ ? !,.=*//*?!,.=-]*$", widget.get()): + widget2.delete(0,"end") + widget2.insert(0,jaconv.h2z(text.upper(), kana=True, digit=True, ascii=True)) + else: + tkinter.messagebox.showerror(title="Error", message=self.tr["Fw error"]) + + + def open_p2b(self,parent): + filetypes = [('Pms2bemani Files', '*.p2b'), + ('All Files', '*.*')] + filename = fd.askopenfilename( + title='Open a file', + #save folder + initialdir = "/áéá", + filetypes=filetypes) + #check we select a file + if filename == '': + return + if filename.endswith('.p2b'): + #load translation + p2b_file = open(filename) + p2b__data = json.load(p2b_file) + parent.title(filename.split("/")[-1]) + self.current_file = filename + self.p2b_to_fields(p2b__data,parent) + + + def save_as(self,parent): + files = [('Pms2bemani Files', '*.p2b'), + ('All Files', '*.*')] + #get current file name + file_now = '' + if self.current_file != '': + file_now=self.current_file.split("/")[-1] + file = fd.asksaveasfile(filetypes = files, defaultextension = files, + initialfile=file_now) + if file is None: # asksaveasfile return `None` if dialog closed with "cancel". + return + file.write(self.fields_to_p2b()) + self.current_file = file.name + parent.title(file.name.split("/")[-1]) + self.menu_file.entryconfig(2, state=ACTIVE) + file.close() + + def save(self): + with open(self.current_file, 'w') as file: + file.write(self.fields_to_p2b()) + file.close() + + + def fields_to_p2b(self): + data = {} + #get data for our file + data["Name"]=self.box_name.get() + data["Music ID"]=self.box_music_id.get() + data["Keysounds folder"]=self.box_keysounds.get() + data["Banner"]=self.box_banner.get() + data["Battle Mode File"]=self.box_input_bp.get() + data["Easy Chart File"]=self.box_input_ep.get() + data["Normal Chart File"]=self.box_input_np.get() + data["Hyper Chart File"]=self.box_input_hp.get() + data["Ex Chart File"]=self.box_input_op.get() + data["FW title"]=self.box_fw_title.get() + data["FW artist"]=self.box_fw_artist.get() + data["FW genre"]=self.box_fw_genre.get() + data["Title"]=self.box_title.get() + data["Artist"]=self.box_artist.get() + data["Genre"]=self.box_genre.get() + data["Chara 1"]=self.box_chara_1.get() + data["Chara 2"]=self.box_chara_2.get() + data["Has battle hyper"]=self.has_battle_var.get() + data["Hariai is jacket"]=self.is_jacket_var.get() + data["Folder"]=self.value_inside_folder.get() + + category_data = {} + for label, value in zip(self.category_des, self.vars_category): + category_data[label] = value.get() + data["Categories"]=category_data + + data["CS Version"]=self.value_inside_cs.get() + + mask_data = {} + for label, value in zip(self.mask_des, self.vars_mask): + mask_data[label] = value.get() + data["Mask"]=mask_data + + data["Chara position X"]=self.box_chara_position_x.get() + data["Chara position Y"]=self.box_chara_position_y.get() + data["Preview file"]=self.box_preview_file.get() + data["Preview offset"]=self.box_preview_offset.get() + data["Preview duration"]=self.box_preview_duration.get() + data["New chart format"]=self.new_chart_format.get() + data["Background"]=self.box_background.get() + data["Hariai"]=self.box_hariai.get() + data["Output folder"]=self.box_output.get() + + return(json.dumps(data)) + + def p2b_to_fields(self,data,parent): + + self.replace_value(self.box_name,data["Name"]) + self.replace_value(self.box_music_id,data["Music ID"]) + self.replace_value(self.box_keysounds,data["Keysounds folder"]) + self.replace_value(self.box_banner,data["Banner"]) + self.replace_value(self.box_input_bp,data["Battle Mode File"]) + self.replace_value(self.box_input_ep,data["Easy Chart File"]) + self.replace_value(self.box_input_np,data["Normal Chart File"]) + self.replace_value(self.box_input_hp,data["Hyper Chart File"]) + self.replace_value(self.box_input_op,data["Ex Chart File"]) + self.replace_value(self.box_fw_title,data["FW title"]) + self.replace_value(self.box_fw_artist,data["FW artist"]) + self.replace_value(self.box_fw_genre,data["FW genre"]) + self.replace_value(self.box_title,data["Title"]) + self.replace_value(self.box_artist,data["Artist"]) + self.replace_value(self.box_genre,data["Genre"]) + self.replace_value(self.box_chara_1,data["Chara 1"]) + self.replace_value(self.box_chara_2,data["Chara 2"]) + self.has_battle_var.set(data["Has battle hyper"]) + self.is_jacket_var.set(data["Hariai is jacket"]) + self.value_inside_folder.set(data["Folder"]) + + for label, value in zip(self.category_des, self.vars_category): + value.set(data["Categories"][label]) + + self.value_inside_cs.set(data["CS Version"]) + + + for label, value in zip(self.mask_des, self.vars_mask): + value.set(data["Mask"][label]) + + self.replace_value(self.box_chara_position_x,data["Chara position X"]) + self.replace_value(self.box_chara_position_y,data["Chara position Y"]) + self.replace_value(self.box_preview_file,data["Preview file"]) + self.replace_value(self.box_preview_offset,data["Preview offset"]) + self.replace_value(self.box_preview_duration,data["Preview duration"]) + self.new_chart_format.set(data["New chart format"]) + self.replace_value(self.box_background,data["Background"]) + self.replace_value(self.box_hariai,data["Hariai"]) + self.replace_value(self.box_output,data["Output folder"]) + + #clean images + self.clean_image(parent,"bg",self.box_background) + self.clean_image(parent,"banner",self.box_banner) + self.clean_image(parent,"hariai",self.box_hariai) + #insert images + if(data["Banner"]!=''): + self.insert_image(parent,data["Banner"],self.box_banner,"banner") + if(data["Background"]!=''): + self.insert_image(parent,data["Background"],self.box_background,"bg") + if(data["Hariai"]!=''): + self.insert_image(parent,data["Hariai"],self.box_hariai,"hariai") + self.menu_file.entryconfig(2, state=ACTIVE) + + def new_fields(self,parent): + #clean all fields + self.replace_value(self.box_name,"") + self.replace_value(self.box_music_id,"") + self.replace_value(self.box_keysounds,"") + self.replace_value(self.box_banner,"") + self.replace_value(self.box_input_bp,"") + self.replace_value(self.box_input_ep,"") + self.replace_value(self.box_input_np,"") + self.replace_value(self.box_input_hp,"") + self.replace_value(self.box_input_op,"") + self.replace_value(self.box_fw_title,"") + self.replace_value(self.box_fw_artist,"") + self.replace_value(self.box_fw_genre,"") + self.replace_value(self.box_title,"") + self.replace_value(self.box_artist,"") + self.replace_value(self.box_genre,"") + self.replace_value(self.box_chara_1,"") + self.replace_value(self.box_chara_2,"") + self.has_battle_var.set(False) + self.is_jacket_var.set(False) + self.value_inside_folder.set(None) + + for label, value in zip(self.category_des, self.vars_category): + value.set(0) + + self.value_inside_cs.set(None) + + + for label, value in zip(self.mask_des, self.vars_mask): + value.set(0) + + self.replace_value(self.box_chara_position_x,0) + self.replace_value(self.box_chara_position_y,0) + self.replace_value(self.box_preview_file,"") + self.replace_value(self.box_preview_offset,0) + self.replace_value(self.box_preview_duration,0) + self.new_chart_format.set(False) + self.replace_value(self.box_background,"") + self.replace_value(self.box_hariai,"") + self.replace_value(self.box_output,"") + + #clean images + self.clean_image(parent,"bg",self.box_background) + self.clean_image(parent,"banner",self.box_banner) + self.clean_image(parent,"hariai",self.box_hariai) + self.current_file = '' + self.menu_file.entryconfig(2, state=DISABLED) + parent.title("Pms2bemani") + + + def replace_value(self,widget,value): + widget.delete(0,"end") + widget.insert(0,value) + + + def options(self,parent): + # Toplevel object which will + # be treated as a new window + ctWin = Toplevel(parent) + # sets the title of the + # Toplevel widget + ctWin.title(self.tr["Options"]) + for i in range(4): + ctWin.columnconfigure(i, weight=10) + #python command + self.tag_command = tkinter.Label(ctWin, text=self.tr["Python command"]) + self.tag_command.grid(column=0, row=0,sticky="W",pady = 2) + self.box_command= tkinter.Entry(ctWin) + self.box_command.grid(column=1, row=0,sticky='ew') + self.tag_command_caption = tkinter.Label(ctWin, text=self.tr["Command warning"]) + self.tag_command_caption.grid(column=0, row=1,sticky="W",pady = 5) + + options = self.load_config_file() + self.replace_value(self.box_command,options["command"]) + #save options + self.btn_save_options = tkinter.Button(ctWin,text=self.tr["Save"],command=lambda: self.save_config_file()) + self.btn_save_options.grid(column=1, row=4,sticky="WE") + + ctWin.transient(parent) + ctWin.grab_set() + parent.wait_window(ctWin) + + + def load_config_file(self): + config_file = open('gui_assets/config.json') + return(json.load(config_file)) + + def save_config_file(self): + data = {} + #get data for our file + data["command"]=self.box_command.get() + with open('gui_assets/config.json', 'w') as file: + file.write(json.dumps(data)) + file.close() + + def delete_window(self,parent): + #check a path exist so we can split + file = self.current_file + if self.current_file !='': + file = self.current_file.split("/")[-1] + + message = self.tr["Close message"] % ( + file or "this file") + save = messagebox.askyesnocancel( + message=message, + title="Pms2bemani", + default=messagebox.YES, + ) + if save: + # Cerrar la ventana. + if self.current_file !='': + self.save() + parent.destroy() + return + else: + self.save_as(parent) + #check we make the safe, + #if not will repeat ask + if self.current_file !='': + parent.destroy() + if self.current_file =='': + self.delete_window(parent) + elif save == False: + parent.destroy() + + def chara_selection(self,parent,widget): + # Toplevel object which will + # be treated as a new window + ctWin = Toplevel(parent) + # sets the title of the + # Toplevel widget + ctWin.title("Chara selector") + ctWin.geometry("200x200") + self.grid_columnconfigure(0, weight=0) + self.grid_columnconfigure(1, weight=0) + self.grid_rowconfigure(0, weight=0) + self.grid_rowconfigure(1, weight=0) + + #creating text box + e = Entry(ctWin) + e.pack(side='top', fill='x', expand=True) + e.bind('', self.checkkey) + + #creating list box + self.lb = Listbox(ctWin) + self.lb.pack(side='top', fill='x', expand=True) + self.lb.bind('<>', lambda eff: self.onselect(eff,widget)) + self.update(self.l) + + + ctWin.transient(parent) + ctWin.grab_set() + parent.wait_window(ctWin) + + # Function for checking the + # key pressed and updating + # the listbox + def checkkey(self,event): + + value = event.widget.get() + + # get data from l + if value == '': + data = self.l + else: + data = [] + for item in self.l: + if value.lower() in item.lower(): + data.append(item) + + # update data in listbox + self.update(data) + + + def update(self,data): + # clear previous data + self.lb.delete(0, 'end') + + # put new data + for item in data: + self.lb.insert('end', item) + + def onselect(self,event,widget): + # Note here that Tkinter passes an event object to onselect() + w = event.widget + index = int(w.curselection()[0]) + value = w.get(index) + self.replace_value(widget,value) + + def chara_txt_to_data(self): + # Using readlines() + file = open('gui_assets/chara_list.txt', 'r',encoding="utf8") + Lines = file.readlines() + charas = [] + # Strips the newline character + for line in Lines: + charas.append(line.split(',')[0].replace("'",'').strip()) + return charas + + + +if __name__ == "__main__": + + #start our app + window = tkinter.Tk() + app = Application(window) + window.mainloop() \ No newline at end of file diff --git a/pms2bemani/pms2bemani/requirements.txt b/pms2bemani/pms2bemani/requirements.txt index fd98c08..9d21705 100644 --- a/pms2bemani/pms2bemani/requirements.txt +++ b/pms2bemani/pms2bemani/requirements.txt @@ -1,2 +1,5 @@ ifstools==1.13 -pydub==0.23.1 \ No newline at end of file +pydub==0.23.1 +jaconv==0.3 +lxml==4.9.1 +Pillow==8.3.1 \ No newline at end of file