From 09018b4b4d82fd235a9e2deb2ab7f976b32b17f5 Mon Sep 17 00:00:00 2001 From: PostScriptReal <149461738+PostScriptReal@users.noreply.github.com> Date: Fri, 26 Sep 2025 13:42:48 +1000 Subject: [PATCH 1/4] Bugfix and a slight code refactor - The Batch manager will now no longer treat items selected with CTRL the same as items selected with SHIFT. - Options menu now no longer uses magic numbers to refer to the tab you've selected. --- menus.py | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/menus.py b/menus.py index f05feca..945de31 100644 --- a/menus.py +++ b/menus.py @@ -16,8 +16,12 @@ from platform import freedesktop_os_release as distroInfo import pyperclip +# Batch manager tabs DECOMP_TAB = 0 COMP_TAB = 1 +# Options menu tabs +GENERAL_TAB = 0 +MODELV_TAB = 1 # To make things easier for myself, I'm making a new class that contains common values that won't (or usually doesn't) change for each menu. class MenuTemp(): @@ -552,7 +556,7 @@ def cPathChk(self, e=False): curMDL = batch[selection[0]] curMDL.output = self.cPathVar.get() elif not focus.get(0).startswith("Select a folder of "): - mdls = batch[int(selection[0]):selection[len(selection)-1]+1] + mdls = self.getFromSelection(selection) for i in mdls: i.output = self.cPathVar.get() else: @@ -561,7 +565,7 @@ def cPathChk(self, e=False): curMDL = batch[selection[0]] curMDL.output = "out" elif not focus.get(0).startswith("Select a folder of "): - mdls = batch[int(selection[0]):selection[len(selection)-1]+1] + mdls = self.getFromSelection(selection) for i in mdls: i.output = "out" @@ -593,7 +597,7 @@ def getCPath(self): curMDL.output = "out" self.cPathVar.set("Please specify an ABSOLUTE path!") elif not focus.get(0).startswith("Select a folder of "): - mdls = batch[int(selection[0]):selection[len(selection)-1]+1] + mdls = self.getFromSelection(selection) for i in mdls: if os.path.isabs(self.cPathVar.get()): i.output = self.cPathVar.get() @@ -645,6 +649,23 @@ def switchTabComp(self): self.mdl_list.grid_remove() self.qc_list.grid(column=0, row=1) + def getFromSelection(self, selection): + if self.curTab == DECOMP_TAB: + batch = self.curDBatch + else: + batch = self.curCBatch + mdls = [] + count = -1 + selCount = 0 + for b in batch: + count += 1 + if selCount > len(selection)-1: + break + if count == int(selection[selCount]): + selCount += 1 + mdls.append(b) + return mdls + def lbSelHandler(self, e=None): try: if self.curTab == DECOMP_TAB: @@ -667,7 +688,8 @@ def lbSelHandler(self, e=None): self.cPath.unlock() self.cPathVar.set(curMDL.output) elif not focus.get(0).startswith("Select a folder of "): - mdls = batch[int(selection[0]):selection[len(selection)-1]+1] + # mdls = batch[int(selection[0]):selection[len(selection)-1]+1] + mdls = self.getFromSelection(selection) skipVal = mdls[0].skip outputVal = mdls[0].output defaultOpts = False @@ -709,7 +731,7 @@ def skipModel(self): curMDL = batch[selection[0]] curMDL.skip = self.skipMDLvar.get() elif not focus.get(0).startswith("Select a folder of "): - mdls = batch[int(selection[0]):selection[len(selection)-1]+1] + mdls = self.getFromSelection(selection) for i in mdls: i.skip = self.skipMDLvar.get() @@ -2109,7 +2131,7 @@ def show(self): class OptionsMenu(): def __init__(self, template, master, thmecallback, updFunc, startHidden:bool=False): - self.curPage = 0 + self.curPage = GENERAL_TAB self.hidden = startHidden self.master = master thme = template.thme @@ -2315,7 +2337,7 @@ def checkNewThemes(self): return False def genPg(self): - self.curPage = 0 + self.curPage = GENERAL_TAB self.setupLabel.grid(column=1, row=1, sticky="w") self.themeCBox.grid(column=2, row=1, sticky="w") self.nameLabel.grid(column=1, row=2, sticky="w") @@ -2342,7 +2364,7 @@ def genPg(self): self.setMVP.grid_remove() def hlmvPg(self): - self.curPage = 1 + self.curPage = MODELV_TAB self.setupLabel.grid_remove() self.themeCBox.grid_remove() self.nameLabel.grid_remove() @@ -2518,7 +2540,7 @@ def show(self): self.pageButtons.grid(row=0, column=1, sticky="nsew", columnspan=10) self.generalButton.grid(row=0, column=1, sticky="w") self.hlmvButton.grid(row=0, column=2, sticky="w") - if self.curPage == 0: + if self.curPage == GENERAL_TAB: self.setupLabel.grid(column=1, row=1, sticky="w") self.themeCBox.grid(column=2, row=1, sticky="w") self.nameLabel.grid(column=1, row=2, sticky="w") @@ -2538,7 +2560,7 @@ def show(self): self.distroLabel.grid(column=1, row=8, sticky="w") self.distroSel.grid(column=2, row=8, sticky="w") self.restartReq1.grid(column=3, row=8, sticky="w") - elif self.curPage == 1: + elif self.curPage == MODELV_TAB: self.hlmvLabel.grid(column=1, row=1, sticky="w") self.hlmvCBox.grid(column=2, row=1, sticky="w") self.mvPathLabel.grid(column=1, row=2, sticky="w") From a588537f0ef95dde470347cb299ea442998ff12a Mon Sep 17 00:00:00 2001 From: PostScriptReal <149461738+PostScriptReal@users.noreply.github.com> Date: Fri, 26 Sep 2025 21:12:57 +1000 Subject: [PATCH 2/4] Alpha MDL decompiling improvements - Snark will now check the MDL version instead of relying on the usage of Xash3D's decompiler, speeding up the decompilation process of v6 MDLs. - There are now quick setup presets pertaining to the modeler you use. - Snark now modifies the output from GeckoN's v6 MDL decompiler to be easier to work with. --- helpers.py | 65 ++++++++++++++++- menus.py | 182 ++++++++++++++++++++++++++++------------------ save/options.json | 3 +- 3 files changed, 177 insertions(+), 73 deletions(-) diff --git a/helpers.py b/helpers.py index 04411ca..d4a84a9 100644 --- a/helpers.py +++ b/helpers.py @@ -433,4 +433,67 @@ def __init__(self, name:str, qcLoc:str, output:str): self.name = name self.qcLoc, self.mdlLoc = qcLoc, qcLoc self.skip = False - self.output = output \ No newline at end of file + self.output = output + +class AlphaPrettify(): + + def __init__(self, cmdOut:str, texSubFolder:bool, mdlDir:str): + self.cmdOut = cmdOut.split('\n') + self.texSF = texSubFolder + self.mDir = mdlDir + self.qcLoc = os.path.join(self.mDir, self.cmdOut[6].replace("QC script: MDL6job/", "")) + with open(self.qcLoc, 'r') as qc: + self.qcDat = qc.readlines() + + self.qcDat.insert(6, "\nOutput modified by Snark, the alternative to Crowbar for GoldSRC!\n") + self.qcDat.insert(7, "Github: https://github.com/PostScriptReal/Snark_Compiler Gamebanana: https://gamebanana.com/tools/19255\n") + self.qcDat.insert(8, "\n") + + texFolder = os.path.join(self.mDir, 'textures') + if self.texSF: + try: + os.mkdir(texFolder) + except: + pass + for f in os.listdir(self.mDir): + if f.endswith('.bmp'): + shutil.copy(os.path.join(self.mDir, f), texFolder) + os.remove(os.path.join(self.mDir, f)) + cdLine = self.qcDat.index('$cd ".\\"\n') + cdtexLine = self.qcDat.index('$cdtexture \".\\"\n') + self.qcDat[cdLine] = '$cd \"./\"\n' + self.qcDat[cdtexLine] = '$cdtexture \"./textures/\"\n' + else: + cdLine = self.qcDat.index('$cd ".\\"\n') + cdtexLine = self.qcDat.index('$cdtexture \".\\"\n') + self.qcDat[cdLine] = '$cd \"./\"\n' + self.qcDat[cdtexLine] = '$cdtexture \"./\"\n' + + try: + animsFolder = os.path.join(self.mDir, 'anims') + except: + pass + try: + os.mkdir(animsFolder) + except: + pass + count = -1 + for l in self.cmdOut: + if l.startswith("Sequence:"): + animF = l.replace("Sequence: MDL6job/", "") + shutil.copy(os.path.join(self.mDir, animF), animsFolder) + os.remove(os.path.join(self.mDir, animF)) + animName = f"\"{animF.replace('.smd', '')}\"" + for s in self.qcDat: + count += 1 + if s.startswith('$sequence'): + if s.find(animName) != -1: + substringStart = s.find(animName)+len(animName)+1 + substring = s[substringStart:] + newSS = substring.replace(animName, f"\"anims/{animName.replace('\"', "", 1)}") + self.qcDat[count] = s.replace(substring, newSS) + break + count = -1 + self.newQC = open(self.qcLoc, 'w') + self.newQC.write(''.join(self.qcDat)) + self.newQC.close() \ No newline at end of file diff --git a/menus.py b/menus.py index 945de31..ba0af74 100644 --- a/menus.py +++ b/menus.py @@ -8,7 +8,7 @@ import subprocess import shutil import datetime -from helpers import BoolEntry, Console, BoolSpinbox, QCHandler, HyperlinkImg, Game, GamesHandler, BatchMDL +from helpers import * import json import sys import jsonc @@ -840,14 +840,25 @@ def __init__(self, template, master, batchManager:BatchManagerM, startHidden:boo } } } + self.modelerPresets = { + "presets": { + "Blender+Maya": True, + "FRAG+MS3D": False + } + } presetNames = list(self.presets["presets"].keys()) + modelerNames = list(self.modelerPresets["presets"].keys()) self.quickStpLbl = Label(self.quick, text="Quick Setup Presets: ") self.setupLabel = Label(master, text="MDL Input: ") self.nameLabel = Label(master, text="Output: ") - self.presetSel = ttk.Combobox(self.quick, values=presetNames) + self.presetSel = ttk.Combobox(self.quick, values=presetNames, width=12) self.presetSel.current(self.options["defDPreset"]) self.presetDat = self.presets["presets"][self.presetSel.get()] self.presetSel.bind("<>", self.chPreset) + self.mdlPresetSel = ttk.Combobox(self.quick, values=modelerNames, width=12) + self.mdlPresetSel.current(self.options["defMDLPreset"]) + self.mdlPresetDat = self.modelerPresets["presets"][self.mdlPresetSel.get()] + self.mdlPresetSel.bind("<>", self.chMDLpreset) self.name = StringVar() self.nameEntry = Entry(master, textvariable=self.name, width=self.widthFix-self.linuxWFix) self.nameEntry.bind("", self.inputHandler) @@ -950,6 +961,10 @@ def chPreset(self, e=False): self.mVal.set(self.presetDat["-m"]) self.uVal.set(self.presetDat["-u"]) self.vVal.set(self.presetDat["-V"]) + + def chMDLpreset(self, e=False): + self.presetDat = self.modelerPresets["presets"][self.mdlPresetSel.get()] + self.tVal.set(self.presetDat) def applyTheme(self, master): style= ttk.Style() @@ -1004,6 +1019,9 @@ def updateOpt(self, key, value): if key == "defDPreset": self.presetSel.current(value) self.chPreset() + elif key == "defMDLPreset": + self.mdlPresetSel.current(value) + self.chMDLpreset() elif key == "linuxFix": if self.options["linuxFix"] == "Cinnamon": self.linuxWFix = 2 @@ -1031,6 +1049,7 @@ def show(self): self.quick.grid(column=0,row=2,sticky="nsew", columnspan=10) self.quickStpLbl.grid(column=0, row=2, sticky="w") self.presetSel.grid(column=1,row=2) + self.mdlPresetSel.grid(column=2,row=2, padx=(10,0)) self.advOpt.grid(column=0, row=3, sticky="nsew", columnspan=10, pady=(20,0)) self.advOptR2.grid(column=0, row=2, sticky="nsew", columnspan=10) self.advOptLabel.grid(column=0, row=0, sticky="w") @@ -1124,6 +1143,18 @@ def getArgs(self): print(cmdArgs) return(cmdArgs) + def checkMDLversion(self, mdlLoc:str): + mdlLoc = mdlLoc + # For anyone who doesn't know, the default MDL version is 10. + fileVer = 10 + try: + with open(mdlLoc, 'rb') as mdlF: + mdlF.seek(4) # Move to the 5th byte (index 4) + fileVer = int.from_bytes(mdlF.read(1)) + except: + print("COULDN\'T FIND MDL VERSION, DEFAULTING TO 10") + return fileVer + def startDecomp(self): SINGLE = False BATCH = True @@ -1164,51 +1195,51 @@ def singleDec(self, mdl:str, out:str, batch:bool, mdlName:str="", fallback:bool= decOut = f"./{mdlName}/" gotArgs = False cmdArgs = self.getArgs() - error = False if not cmdArgs == "" or not cmdArgs == " ": gotArgs = True if output == "" or output == None: output = os.path.join(os.path.dirname(mdl), "Decompile/") if not os.path.exists(output): os.mkdir(output) - tOutput = '' - if sys.platform == 'linux': - if gotArgs: - tOutput = subprocess.getoutput(f'./third_party/mdldec -a {cmdArgs} \"{mdl}\" \"{output}\"') - else: - tOutput = subprocess.getoutput(f'./third_party/mdldec -a \"{mdl}\" \"{output}\"') - elif sys.platform == 'win32': - if gotArgs: - tOutput = subprocess.getoutput(f'\"{os.getcwd()}/third_party/mdldec.exe\" -a {cmdArgs} \"{mdl}\" \"{output}\"') - else: - tOutput = subprocess.getoutput(f'\"{os.getcwd()}/third_party/mdldec.exe\" -a \"{mdl}\" \"{output}\"') - # I don't have a Mac so I can't compile mdldec to Mac targets :( - # So instead I have to use wine for Mac systems - """elif sys.platform == 'darwin': - tOutput = subprocess.getoutput(f'wine third_party/mdldec_win32.exe \"{mdl}\"')""" - # Checking for errors (especially the 'unknown Studio MDL format') + mdlVer = self.checkMDLversion(mdl) + print(f"MDL version: {mdlVer}") v6MDL = False - if tOutput.find("unknown Studio MDL format version 6") != -1: - error = True + if mdlVer != 6: + tOutput = '' + if sys.platform == 'linux': + if gotArgs: + tOutput = subprocess.getoutput(f'./third_party/mdldec -a {cmdArgs} \"{mdl}\" \"{output}\"') + else: + tOutput = subprocess.getoutput(f'./third_party/mdldec -a \"{mdl}\" \"{output}\"') + elif sys.platform == 'win32': + if gotArgs: + tOutput = subprocess.getoutput(f'\"{os.getcwd()}/third_party/mdldec.exe\" -a {cmdArgs} \"{mdl}\" \"{output}\"') + else: + tOutput = subprocess.getoutput(f'\"{os.getcwd()}/third_party/mdldec.exe\" -a \"{mdl}\" \"{output}\"') + # I don't have a Mac so I can't compile mdldec to Mac targets :( + # So instead I have to use wine for Mac systems + """elif sys.platform == 'darwin': + tOutput = subprocess.getoutput(f'wine third_party/mdldec_win32.exe \"{mdl}\"')""" + else: + v6MDL = True + shutil.copy(mdl, './') + v6MDLname = os.path.basename(mdl) if sys.platform == 'linux': - v6MDL = True - shutil.copy(mdl, './') - v6MDLname = os.path.basename(mdl) tOutput = subprocess.getoutput(f'wine \"{os.getcwd()}/third_party/mdl6dec.exe\" \"{v6MDLname}\" -p \"MDL6job\"') - os.remove(f"{v6MDLname}") - # Moving the decompiler output to the output folder! - if not os.path.exists(output): - os.mkdir(output) - for f in os.listdir('MDL6job'): - print(f) - shutil.copy(f"MDL6job/{f}", os.path.join(output, f)) - shutil.rmtree('MDL6job') else: - v6MDL = True - v6MDLname = os.path.basename(mdl) - tOutput = subprocess.getoutput(f'\"{os.getcwd()}/third_party/mdl6dec.exe\" \"{mdl}\" -p \"{output}\"') - elif tOutput.find("ERROR:") != -1: - error = True + tOutput = subprocess.getoutput(f'\"{os.getcwd()}/third_party/mdl6dec.exe\" \"{v6MDLname}\" -p \"MDL6job\"') + os.remove(f"{v6MDLname}") + AlphaPrettify(tOutput, self.tVal.get(), os.path.join(os.getcwd(), 'MDL6job')) + # Moving the decompiler output to the output folder! + if not os.path.exists(output): + os.mkdir(output) + for f in os.listdir('MDL6job'): + print(f) + try: + shutil.copy(f"MDL6job/{f}", os.path.join(output, f)) + except: + shutil.copytree(os.path.join(os.getcwd(), 'MDL6job', f), os.path.join(output, f), dirs_exist_ok=True) + shutil.rmtree('MDL6job') print(tOutput) if not batch: self.console.setOutput(tOutput) @@ -1218,34 +1249,6 @@ def singleDec(self, mdl:str, out:str, batch:bool, mdlName:str="", fallback:bool= log = open(f"logs/decomp-{curDate}.txt", 'w') log.write(tOutput) log.close() - # Moving files to output directory (this is a workaround to a bug with Xash3D's model decompiler, where absolute paths result in an error) - """if not error: - if batch and fallback and not os.path.exists(os.path.dirname(output)): - os.mkdir(os.path.dirname(output)) - if not os.path.exists(output): - os.mkdir(output) - anims = os.path.join(decOut, 'anims/') - texFolder = os.path.join(decOut, 'textures/') - for f in os.listdir(decOut): - print(f) - if f.endswith("smd") or f.endswith("qc"): - shutil.copy(f"{decOut}/{f}", os.path.join(output, f)) - os.remove(f"{decOut}/{f}") - elif f.endswith("bmp") and not self.tVal.get(): - shutil.copy(f"{decOut}/{f}", os.path.join(output, f)) - os.remove(f"{decOut}/{f}") - shutil.copytree(anims, os.path.join(output, 'anims/')) - if self.tVal.get(): - shutil.copytree(texFolder, os.path.join(output, 'textures/')) - try: - shutil.rmtree(texFolder) - except: - pass - try: - shutil.rmtree(anims) - except: - pass - shutil.rmtree(decOut)""" class CompMenu(): def __init__(self, template, master, batchManager:BatchManagerM, startHidden:bool=False): @@ -2140,7 +2143,7 @@ def __init__(self, template, master, thmecallback, updFunc, startHidden:bool=Fal self.updFunc = updFunc # Grabbing options self.options = template.options - self.curJSONVer = 6 + self.curJSONVer = 7 # Checking if options JSON is from a previous version... if not self.options["version"] >= self.curJSONVer: self.upgradeJSON() @@ -2148,9 +2151,11 @@ def __init__(self, template, master, thmecallback, updFunc, startHidden:bool=Fal self.pageButtons = Frame(master, borderwidth=2, bg=thme["bg"]) self.generalButton = Button(self.pageButtons, text="General", cursor="hand2", command=self.genPg) self.hlmvButton = Button(self.pageButtons, text="Model Viewers", cursor="hand2", command=self.hlmvPg) + # General options self.setupLabel = Label(master, text=f"Theme: ", background=thme["bg"], foreground=thme["txt"]) self.nameLabel = Label(master, text="Starting directory: ", background=thme["bg"], fg=thme["txt"]) + themes = ["Freeman", "Shephard", "Calhoun", "Cross"] usrThemes = self.checkNewThemes() if not usrThemes == False: @@ -2165,20 +2170,24 @@ def __init__(self, template, master, thmecallback, updFunc, startHidden:bool=Fal self.themeCBox = ttk.Combobox(master, cursor="hand2", values=themes) self.themeCBox.bind("<>", thmecallback) self.themeCBox.set(self.options["theme"]) + self.startFSV = StringVar(master, value=self.options["startFolder"]) # I just realised I shortened the name so it looks like it's name is Start Fent. # I promise you there is no illicit drugs to be found anywhere in the program lol. self.startFent = Entry(master, textvariable=self.startFSV) self.setSF = Button(master, text="Set Start Folder", cursor="hand2", command=self.chSF) + self.forceDefB = BooleanVar(master, value=self.options["forceDefPaths"]) self.fdLabel = Label(master, text="Prioritise default paths:") self.forceDefault = Checkbutton(master, command=self.chFDP, variable=self.forceDefB) + # Model Viewer Options self.hlmvLabel = Label(master, text="Model Viewer: ") hlmvValues = ["None", "Half-Life Asset Manager", "Other"] self.hlmvCBox = ttk.Combobox(master, cursor="hand2", values=hlmvValues) self.hlmvCBox.current(self.options["gsMV"]["selectedMV"]) self.hlmvCBox.bind("<>", self.setMV) + self.mvPathLabel = Label(master, text="Path to model viewer: ") self.mvPathVar = StringVar(master, value="Path to model viewer (if \"Other\" is selected)") self.mvPathEnt = BoolEntry(master, textvariable=self.mvPathVar, placeholder="Path to model viewer (if \"Other\" is selected)") @@ -2186,20 +2195,25 @@ def __init__(self, template, master, thmecallback, updFunc, startHidden:bool=Fal if self.options["gsMV"]["selectedMV"] > 1: self.mvPathEnt.unlock() self.mvPathVar.set(self.options["gsMV"]["csPath"]) + # Options for setting defaults for profiles self.defCLabel = Label(master, text=f"Default Compiler: ", background=thme["bg"], foreground=thme["txt"]) self.defGLabel = Label(master, text="Default Game: ", background=thme["bg"], fg=thme["txt"]) self.defPLabel = Label(master, text="Default Decompile Preset:") + self.defMDLLabel = Label(master, text="Default Modeler Preset:") + cList = open("save/compilers.txt", "r") cOptions = cList.read().split('\n') cOptions.pop(len(cOptions)-1) self.compSel = ttk.Combobox(master, values=cOptions) self.compSel.bind("<>", self.setCmp) self.compSel.current(self.options["defComp"]) + gList = open("save/games.txt", "r") self.gOptions = gList.read().split('\n') self.gOptions.pop(len(self.gOptions)-1) gList.close() + self.games = GamesHandler(self.gOptions) self.gameSel = ttk.Combobox(master, values=self.games.gNames) self.gameSel.bind("<>", self.setGame) @@ -2232,14 +2246,29 @@ def __init__(self, template, master, thmecallback, updFunc, startHidden:bool=Fal } } } + self.modelerPresets = { + "presets": { + "Blender+Maya": True, + "FRAG+MS3D": False + } + } presetNames = list(self.presets["presets"].keys()) + modelerNames = list(self.modelerPresets["presets"].keys()) + self.presetSel = ttk.Combobox(master, values=presetNames) self.presetSel.current(self.options["defDPreset"]) self.presetDat = self.presets["presets"][self.presetSel.get()] self.presetSel.bind("<>", self.setDP) + + self.mdlPresetSel = ttk.Combobox(master, values=modelerNames) + self.mdlPresetSel.current(self.options["defMDLPreset"]) + self.mdlPresetDat = self.modelerPresets["presets"][self.mdlPresetSel.get()] + self.mdlPresetSel.bind("<>", self.setDMDL) + self.spLabel = Label(master, text="Save paths: ") self.savePathsB = BooleanVar(master, value=self.options["save_paths"]) self.savePathsCB = Checkbutton(master, command=self.chSP, variable=self.savePathsB) + self.distroLabel = Label(master, text="Distro Resize: ") self.restartReq1 = Label(master, text="(RESTART REQUIRED)") self.distros = ["KDE", "Cinnamon"] @@ -2248,6 +2277,7 @@ def __init__(self, template, master, thmecallback, updFunc, startHidden:bool=Fal self.distroSel.set(self.options["linuxFix"]) self.distroSel.bind("<>", self.setLF) self.distroTT = ToolTip(self.distroSel, "This Linux-only selector will tell Snark which distro variant you use, it will resize itself so everything looks correct on your system when you select the option. If there's still windowing bugs, please create an issue on Github or Gamebanana with your distro information copied from the terminal or the about menu.", background=thme["tt"], foreground=thme["txt"]) + # Tooltips self.themeTT = ToolTip(self.themeCBox, "Changes the program's theme, the built-in themes are: Freeman, Shephard, Calhoun and Cross.", background=thme["tt"], foreground=thme["txt"]) self.startFolderTT = ToolTip(self.startFent, "Sets the directory that the built-in file explorer will start in, the default is the documents folder.", background=thme["tt"], foreground=thme["txt"]) @@ -2287,6 +2317,7 @@ def upgradeJSON(self): except: if distroInfo().get("VARIANT_ID", 'kde').lower() == "cinnamon": linuxWinFix = 'Cinnamon' + defaultModelerPreset = self.options.get("defMDLPreset", 0) if self.options["version"] < 5: savePaths = True upgradePaths = True @@ -2295,6 +2326,7 @@ def upgradeJSON(self): "defComp": defaultComp, "defGame": defaultGame, "defDPreset": defaultDecompPreset, + "defMDLPreset": defaultModelerPreset, "forceDefPaths": forceDefaultPaths, "save_paths": savePaths, "startFolder": startingFolder, @@ -2503,6 +2535,12 @@ def setDP(self, e=False): self.save_options() self.updFunc("defDPreset", opt) + def setDMDL(self, e=False): + opt = self.mdlPresetSel.current() + self.options["defMDLPreset"] = opt + self.save_options() + self.updFunc("defMDLPreset", opt) + def chFDP(self): self.options["forceDefPaths"] = self.forceDefB.get() self.save_options() @@ -2554,12 +2592,14 @@ def show(self): self.defPLabel.grid(column=1, row=6, sticky="w") self.gameSel.grid(column=2, row=5, sticky="w") self.presetSel.grid(column=2, row=6, sticky="w") - self.spLabel.grid(column=1, row=7, sticky="w") - self.savePathsCB.grid(column=2, row=7, sticky="w") + self.spLabel.grid(column=1, row=8, sticky="w") + self.savePathsCB.grid(column=2, row=8, sticky="w") if sys.platform == 'linux': - self.distroLabel.grid(column=1, row=8, sticky="w") - self.distroSel.grid(column=2, row=8, sticky="w") - self.restartReq1.grid(column=3, row=8, sticky="w") + self.distroLabel.grid(column=1, row=9, sticky="w") + self.distroSel.grid(column=2, row=9, sticky="w") + self.restartReq1.grid(column=3, row=9, sticky="w") + self.defMDLLabel.grid(column=1, row=7, sticky="w") + self.mdlPresetSel.grid(column=2, row=7, sticky="w") elif self.curPage == MODELV_TAB: self.hlmvLabel.grid(column=1, row=1, sticky="w") self.hlmvCBox.grid(column=2, row=1, sticky="w") diff --git a/save/options.json b/save/options.json index 56656c4..ed28031 100755 --- a/save/options.json +++ b/save/options.json @@ -2,6 +2,7 @@ "defComp": 0, "defDPreset": 0, "defGame": 0, + "defMDLPreset": 0, "forceDefPaths": false, "gsMV": { "csPath": "", @@ -11,5 +12,5 @@ "save_paths": true, "startFolder": "~/Documents", "theme": "Freeman", - "version": 6 + "version": 7 } \ No newline at end of file From 8648c47fca975e92c053b7fb647a5f76deb8f783 Mon Sep 17 00:00:00 2001 From: PostScriptReal <149461738+PostScriptReal@users.noreply.github.com> Date: Fri, 26 Sep 2025 22:17:10 +1000 Subject: [PATCH 3/4] Bump version to 0.3.3 --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 3b38478..5c2dfe4 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v0.3.2-(OS)-alpha +v0.3.3-(OS)-alpha From 6e51871e2e645382cba27f51f49a2cdbb0d6fc70 Mon Sep 17 00:00:00 2001 From: PostScriptReal <149461738+PostScriptReal@users.noreply.github.com> Date: Fri, 26 Sep 2025 22:49:48 +1000 Subject: [PATCH 4/4] Update README --- README.md | 6 +++--- git_images/decompWin.png | Bin 23519 -> 27486 bytes 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5fffbf0..f402a70 100644 --- a/README.md +++ b/README.md @@ -24,14 +24,14 @@

Why should I use Snark over Crowbar?

It's easier to configure and use!

-

In Crowbar, to decompile a model you would have to fiddle around with settings in order to get your model decompiled properly for GoldSRC. With Snark, you don't need to do any extra configuration, just select an MDL file, select the output folder, set the appropriate preset for the compiler you'd like to use, hit the decompile button and you're set!

+

In Crowbar, to decompile a model, you would have to fiddle around with lots of settings in order to get your model decompiled properly for GoldSRC. With Snark, the whole process is streamlined and optimised for the engine. The options needed by the decompiler are much fewer, and there are quick setup presets ready to tailor it for your preferred compiler and modelling program in no time!

Screenshot of decompile menu -

On top of that, the compiling GUI includes all the command-line options as toggleable checks with tooltips to tell you what they do, so you don't need to check any sort of documentation, official or unofficial to use the advanced features StudioMDL offers its users.

+

On top of that, the compiling GUI includes all the command-line options as toggleable checks with tooltips to tell you what they do, so you don't need to check any sort of documentation, official or unofficial, to use the advanced features StudioMDL offers its users.

Screenshot of compile menu

Natively runs on Windows and Linux!

Snark is written using Python & Tkinter, which means that native support for the major operating systems can be easily offered. You no longer need to run Crowbar under Wine for Linux systems to make models for GoldSRC, instead you can run Snark natively with proper Linux binaries. Wine will still be needed to run the compilers that Snark interfaces with, make sure you have the system package installed instead of the Flatpak!

Better detection for unsupported features with compilers

-

There are many different model compilers for GoldSRC, such as the Sven Co-op compiler that introduce new features that aren't supported in other games utilising the engine. Snark uses a profile system to track which compiler and game you're using so any discrepancies between what the compiler and game supports doesn't go unnoticed by the program. For example, if you use the Svengine compiler with Half-Life instead of Sven Co-op, the compiler will warn you that Half-Life doesn't support 1024px textures or chrome textures that aren't 64x64 resolution if any of them are included in the model files.

+

There are many different model compilers for GoldSRC, such as the Sven Co-op compiler, that introduce new features that aren't supported in other games utilising the engine. Snark uses a profile system to track which compiler and game you're using, so any discrepancies between what the compiler and game supports doesn't go unnoticed by the program. For example, if you use the Svengine compiler with Half-Life instead of Sven Co-op, the compiler will warn you that Half-Life doesn't support 1024px textures or chrome textures that aren't 64x64 resolution if any of them are included in the model files.

Screenshot of compile menu, showing a warning that Half-Life doesn't support high resolution textures

Frequently Asked Questions

diff --git a/git_images/decompWin.png b/git_images/decompWin.png index 99909b7d5dccbb3f84e1a644416bdf1e22e42d3e..42ad7a1152cfb6321cdff9e71e9d683fb76691b6 100644 GIT binary patch literal 27486 zcmbTe1yEeg*7u9MySoM(f(Hu@2^QQnSa5d+mn3)sBpDz`g1h?+8XSV_;E>?%GvDNS z&bjwI?|Z7gx_4KxXS#c8PxtQLz5eUB7L%Z@se+F~gM);Ggs-NmsDp%r;*W%cyn}^- zs3E2*rbfIVd+VskBQFf{0uco?2RRKnB&3>T+y`rPM48D}RYwB}DTo6JDLfhp=?+m9 zzK4Y53qV5pZH0vNEDH&V(gW1`N(#|{?V)PyjfBL{`sWWh;G3);q7u_bO+yLu7d8zZ z9cv`>8V}-S81r4pejwloq7FAvCS58m3xN^2r6viq! zW!rL!ii>iB@^jwKkMZQhhqFY!NX;ixN?DbZXOjN1GMe!T%1F!ffvgm5b$lQSb1-A! z)A+R{H1OEpUaWr)*5Im$IJWAoO3_#lM^W7RwQQ_6RDga;j~H>J4!Ineer_Q}yp_ln zC+uXF6f@TU(@=u;Q|D}m&>zWZ1ta^kZz$)!Tr*mKxXc-}!#8vY+VUPs>g-6!plIn}DV}H>E6apZ*kJs=OvLt5{r9RRd#f zlid1ZE9J_*b+@~so{q#&&gMD2XiJ#4AN2^Jn@2ar7P!S+P3~f|$?ny!5z`Sqm3Tke z`NCp~&CDP6+=iCYDvBIDWTJADsdcJx`@uu5(93masp2T^q(DB{zO_kxk3rYe1K-&;-ZN>M9dHb}@(=9L+MA;8oZY#acSbkS;6fY%v+8KI^Rm3g&uqVfScU3+8X z>F*0P4b2`Im~Qh#$=YwIAP+Bm3ZL06DLq~n-xUZE*TMAJmhYqzRzGfqb(Da1IY_*J z^)$~4NFigMV5Mfu*tGc$7)g@{Tk?AnPaVE^pG{kn`m_)9(u|XHUHULVvWi2gE=;=F zHU~^8n;Keh@wnT$`i@q%<0dP zp{^S^PN>KT&lbdo0%gEQcT_pvrZ&&Ku;3?j=$oB=wc&-D%~iqS%{#t;a`kT6_UP+( zpC<1|OnNOY$xgGEtXggIJouDIVbRwE^qh^K?G-jK@F7`1+Q7}Qc|+X$xm&dBBtmZU z6SI3@Z}tjS&lqd%9chTI3h77!nU*!99KB=WZh`~gyH@W(7;eo>dUf3n@y*5fjlod@ z|M4K9r}~~c}_}x@$1Bz518;ExEar880jZ5shJ52u8qO17JbiN zeI-LuI*TUyQD!yt8RNi=t*WCXe!)z@&mcj=_s%X1u1J$E)|$D|-f7jI zlZyPkbCpwmakKdPc;1}%lc7wNTUFRw6k_>plAf;qx)-6$M+PbY4y`Zofe<1a=WkK| z5=x{Dko(Py+Fa*|R~3Xgv?@e%0DMVzYNhldYl1yZ$1MN~`qgBjENwSuo*@2vgDB5i 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 i0mCIjoz~W7JkOO&M~YuQ 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 G`F{Z70lsJe literal 23519 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 U&&l5bJ+(m&cFypsKVQH9AFOkqAOHXW