From 497a15b5dc0ab13433d8811a9eacf2262876de70 Mon Sep 17 00:00:00 2001 From: AtlasC0R3 <39468657+AtlasC0R3@users.noreply.github.com> Date: Wed, 11 Nov 2020 22:29:22 -0500 Subject: [PATCH] Added program files Just added the actual files that have the program --- main.py | 200 +++++++++++++++++++++++++++++++++ metadata/file_version_info.txt | 44 ++++++++ metadata/logo.ico | Bin 0 -> 76862 bytes metadata/logo.png | Bin 0 -> 10881 bytes metadata/metadata.yml | 5 + tooltip.py | 55 +++++++++ 6 files changed, 304 insertions(+) create mode 100644 main.py create mode 100644 metadata/file_version_info.txt create mode 100644 metadata/logo.ico create mode 100644 metadata/logo.png create mode 100644 metadata/metadata.yml create mode 100644 tooltip.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..c764cf8 --- /dev/null +++ b/main.py @@ -0,0 +1,200 @@ +import os +import shutil +import tkinter +from tkinter import messagebox, filedialog, font +from tkinter.ttk import Progressbar, Button +from tooltip import CreateToolTip +from functools import partial + +runningpath = os.path.dirname(__file__) +appdata = os.environ['LOCALAPPDATA'] + +if os.path.isdir(f'{appdata}\\Roblox'): + print('Roblox directory in AppData installed: continuing.') +else: + tkinter.messagebox.showerror("Roblox directory in AppData directory does not seem to exist. Program halted.") + exit() + +if os.path.isdir(f'{appdata}\\Roblox\\Versions'): + print('Roblox versions directory seem to exist: checking if they actually have crap in them.') + rblxversions = [f.path for f in os.scandir(f'{appdata}\\Roblox\\Versions') if f.is_dir()] + if not rblxversions: + tkinter.messagebox.showerror("There seem to be no currently installed Roblox versions, " + "therefore making it very unlikely any Roblox versions are currently installed. " + "Program halted.") + exit() +else: + tkinter.messagebox.showerror("Roblox versions directory doesn't seem to exist, " + "therefore making it very unlikely any Roblox versions are currently installed. " + "Program halted.") + +for x in rblxversions: + if os.path.isfile(f'{x}\\RobloxPlayerBeta.exe'): + print(f"I found the Roblox engine player directory! {x}") + rblxclient = x + elif os.path.isfile(f'{x}\\RobloxStudioBeta.exe'): + print(f"I found the Roblox engine studio directory! {x}") + rblxstudio = x + +try: + rblxclient +except NameError: + tkinter.messagebox.showerror("I couldn't find any Roblox versions that contain the Roblox engine player. Program halted.") + +rblxsounds = f'{rblxclient}\\content\\sounds' +if not os.path.isdir(rblxsounds): + tkinter.messagebox.showerror("Umm... That's odd, I couldn't find the directory where the sounds are stored.. Program halted, I guess?") + +# Whoo! We made it to the sound files! +expected_sounds = { + "uuhhh": f'{rblxsounds}\\uuhhh.mp3', + "snap": f'{rblxsounds}\\snap.mp3', + "impact_water": f'{rblxsounds}\\impact_water.mp3', + "impact_explosion_03": f'{rblxsounds}\\impact_explosion_03.mp3', + "action_swim": f'{rblxsounds}\\action_swim.mp3', + "action_jump_land": f'{rblxsounds}\\action_jump_land.mp3', + "action_jump": f'{rblxsounds}\\action_jump.mp3', + "action_get_up": f'{rblxsounds}\\action_get_up.mp3', + "action_footsteps_plastic": f'{rblxsounds}\\action_footsteps_plastic.mp3', + "action_falling": f'{rblxsounds}\\action_falling.mp3' +} +expected_backups = { + "uuhhh": f'{rblxsounds}\\uuhhh.mp3.bak', + "snap": f'{rblxsounds}\\snap.mp3.bak', + "impact_water": f'{rblxsounds}\\impact_water.mp3.bak', + "impact_explosion_03": f'{rblxsounds}\\impact_explosion_03.mp3.bak', + "action_swim": f'{rblxsounds}\\action_swim.mp3.bak', + "action_jump_land": f'{rblxsounds}\\action_jump_land.mp3.bak', + "action_jump": f'{rblxsounds}\\action_jump.mp3.bak', + "action_get_up": f'{rblxsounds}\\action_get_up.mp3.bak', + "action_footsteps_plastic": f'{rblxsounds}\\action_footsteps_plastic.mp3.bak', + "action_falling": f'{rblxsounds}\\action_falling.mp3.bak' +} +sounds = {} +replacable_sounds = {} + +for key, value in expected_sounds.items(): + if os.path.isfile(value): + sounds[key] = value + +GuiWindow = tkinter.Tk() +GuiWindow.title('Roblox Sound Replacer') +GuiWindow.resizable(False, False) + +fontlist = tkinter.font.families() +if "Segoe UI" in fontlist: + fontuse = 'Segoe UI' + print("Using Segoe UI font, as it is installed.") +else: + fontuse = 'Arial' + print("Using Arial font, as Segoe UI is not installed.") +labelRow = 0 + +sounds_info = { + "uuhhh": "The Roblox death sound file.", + "snap": "i dont think this sound is used ingame", + "impact_water": "The sound used for landing in water.", + "impact_explosion_03": "This is an explosion sound. It *might* be used in a few games.", + "action_swim": "The sound used for swimming.", + "action_jump_land": "The sound used for landing.", + "action_jump": "The sound used for jumping.", + "action_get_up": "The (rarely used) sound used when the character gets up.", + "action_footsteps_plastic": "The sound used for walking on Plastic material.", + "action_falling": "The sound used for falling.", + "bass": "i dont know and its also not an mp3 file so im not gonna touch that" +} +sounds_textboxes = {} +sounds_browsers = {} + + +def browsefiles(keyparam): + filename = filedialog.askopenfilename(initialdir=runningpath, + title="Select a File", + filetypes=(("*.mp3 files", + "*.mp3*"), + ("all files", + "*.*"))) + sounds_textboxes[keyparam].insert(0, filename) + + +for key, value in sounds.items(): + labelRow = labelRow + 1 + currentLabel = tkinter.Label(GuiWindow, text=key, font=(fontuse, 12)) + currentLabel.grid(column=1, row=labelRow) + CreateToolTip(currentLabel, sounds_info[key]) + labelRow = labelRow + 1 + currentTextbox = tkinter.ttk.Entry(GuiWindow) + sounds_textboxes[key] = currentTextbox + currentTextbox.grid(column=1, row=labelRow, sticky='ew') + labelRow = labelRow + 1 + button_explore = Button(GuiWindow, + text="Browse files", + command=partial(browsefiles, key)) + button_explore.grid(column=1, row=labelRow, sticky='ew') + labelRow = labelRow + 1 + tkinter.ttk.Separator(GuiWindow).grid(column=1, row=labelRow, sticky='ew', pady=5) + +for key, value in expected_sounds.items(): + if os.path.isfile(f'{runningpath}\\{key}.mp3'): + replacable_sounds[key] = f'{runningpath}\\{key}.mp3' + try: + sounds_textboxes[key].insert(0, f'{runningpath}\\{key}.mp3') + except KeyError: + pass + + +def soundreplace(): + for xkey, y in sounds_textboxes.items(): + currentvaluetext = y.get() + if not currentvaluetext == '': + replacable_sounds[xkey] = currentvaluetext + GuiButton['state'] = 'disabled' + progressleap = 100 / len(replacable_sounds.values()) + for xkey, y in replacable_sounds.items(): + if xkey in sounds: + shutil.move(sounds[xkey], f'{sounds[xkey]}.bak') + try: + shutil.copyfile(y, sounds[xkey]) + except FileNotFoundError: + tkinter.messagebox.showerror('File not found', + f'File {y} is missing and therefore could not be copied. ' + f'Action cancelled.') + GuiButton['state'] = 'normal' + progress['value'] = 0 + return + progress['value'] = progress['value'] + progressleap + if progress['value'] == 100: + GuiButton['state'] = 'normal' + tkinter.messagebox.showinfo('Success', 'All sound files have been replaced!') + progress['value'] = 0 + + +def soundrevert(): + GuiRevertButton['state'] = 'disabled' + progressleap = 100 / len(expected_backups.values()) + for xkey, y in expected_backups.items(): + progress['value'] = progress['value'] + progressleap + if os.path.isfile(y): + try: + os.remove(expected_sounds[xkey]) + except FileNotFoundError: + pass # File does not exist. + os.rename(y, expected_sounds[xkey]) + if progress['value'] == 100: + GuiRevertButton['state'] = 'normal' + tkinter.messagebox.showinfo('Success', 'All sound files have been reverted!') + progress['value'] = 0 + + +GuiButton = tkinter.ttk.Button(GuiWindow, text='Replace', command=soundreplace) +GuiButton.grid(column=1, row=labelRow + 2) +CreateToolTip(GuiButton, 'Replaces sound files accordingly.') +GuiRevertButton = tkinter.ttk.Button(GuiWindow, text='Revert', command=soundrevert) +GuiRevertButton.grid(column=1, row=labelRow + 3) +CreateToolTip(GuiRevertButton, 'Reverts any changes to sound files accordingly.') +progress = Progressbar(GuiWindow, orient='horizontal', + length=400, mode='determinate') +progress.grid(column=1, row=labelRow + 4, pady=5) + +print('Launching Tk window') +GuiWindow.mainloop() diff --git a/metadata/file_version_info.txt b/metadata/file_version_info.txt new file mode 100644 index 0000000..1c3bc14 --- /dev/null +++ b/metadata/file_version_info.txt @@ -0,0 +1,44 @@ +# UTF-8 +# +# For more details about fixed file info 'ffi' see: +# http://msdn.microsoft.com/en-us/library/ms646997.aspx + +VSVersionInfo( + ffi=FixedFileInfo( + # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) + # Set not needed items to zero 0. Must always contain 4 elements. + filevers=(1,0,0,0), + prodvers=(1,0,0,0), + # Contains a bitmask that specifies the valid bits 'flags'r + mask=0x3f, + # Contains a bitmask that specifies the Boolean attributes of the file. + flags=0x0, + # The operating system for which this file was designed. + # 0x4 - NT and there is no need to change it. + OS=0x40004, + # The general type of file. + # 0x1 - the file is an application. + fileType=0x1, + # The function of the file. + # 0x0 - the function is not defined for this fileType + subtype=0x0, + # Creation date and time stamp. + date=(0, 0) + ), + kids=[ + StringFileInfo( + [ + StringTable( + u'040904B0', + [StringStruct(u'CompanyName', u'AtlasC0R3'), + StringStruct(u'FileDescription', u'Roblox Sound Replacer'), + StringStruct(u'FileVersion', u'1.0.0.0'), + StringStruct(u'InternalName', u'Roblox Sound Replacer'), + StringStruct(u'LegalCopyright', u''), + StringStruct(u'OriginalFilename', u''), + StringStruct(u'ProductName', u'Roblox Sound Replacer'), + StringStruct(u'ProductVersion', u'1.0.0.0')]) + ]), + VarFileInfo([VarStruct(u'Translation', [1033, 1200])]) + ] +) \ No newline at end of file diff --git a/metadata/logo.ico b/metadata/logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..85ec99f037410b5f5ecce89078123478c5fe61dc GIT binary patch literal 76862 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 literal 0 HcmV?d00001 diff --git a/metadata/metadata.yml b/metadata/metadata.yml new file mode 100644 index 0000000..aff380b --- /dev/null +++ b/metadata/metadata.yml @@ -0,0 +1,5 @@ +Version: 1.0.0.0 +CompanyName: AtlasC0R3 +FileDescription: Roblox Sound Replacer +InternalName: Roblox Sound Replacer +ProductName: Roblox Sound Replacer \ No newline at end of file diff --git a/tooltip.py b/tooltip.py new file mode 100644 index 0000000..8db5314 --- /dev/null +++ b/tooltip.py @@ -0,0 +1,55 @@ +import tkinter + + +class CreateToolTip(object): + """ + create a tooltip for a given widget + """ + + def __init__(self, widget, text='widget info'): + self.waittime = 500 # miliseconds + self.wraplength = 180 # pixels + self.widget = widget + self.text = text + self.widget.bind("", self.enter) + self.widget.bind("", self.leave) + self.widget.bind("", self.leave) + self.id = None + self.tw = None + + def enter(self, event=None): + self.schedule() + + def leave(self, event=None): + self.unschedule() + self.hidetip() + + def schedule(self): + self.unschedule() + self.id = self.widget.after(self.waittime, self.showtip) + + def unschedule(self): + unscheduleid = self.id + self.id = None + if unscheduleid: + self.widget.after_cancel(unscheduleid) + + def showtip(self, event=None): + x, y, cx, cy = self.widget.bbox("insert") + x += self.widget.winfo_rootx() + 25 + y += self.widget.winfo_rooty() + 20 + # creates a toplevel window + self.tw = tkinter.Toplevel(self.widget) + # Leaves only the label and removes the app window + self.tw.wm_overrideredirect(True) + self.tw.wm_geometry("+%d+%d" % (x, y)) + label = tkinter.Label(self.tw, text=self.text, justify='left', + background="#ffffff", relief='solid', borderwidth=1, + wraplength=self.wraplength) + label.pack(ipadx=1) + + def hidetip(self): + tw = self.tw + self.tw = None + if tw: + tw.destroy()