GDLVL/GMD conversion support & Migrate to PySide6

This commit is contained in:
Lncvrt committed 2026-10-20 18:00:40 -07:00
1 parent 69a8af761f
commit 903921d8ce
5 files changed
+91 -30

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
.DS_Store
build/
+12
View File
@@ -0,0 +1,12 @@
# macOS
nuitka --standalone --enable-plugin=pyside6 --macos-create-app-bundle --output-dir=build GDUtils.py
# Windows
nuitka --standalone --enable-plugin=pyside6 --windows-console-mode=disable --output-dir=build GDUtils.py
# Linux
nuitka --standalone --enable-plugin=pyside6 --output-dir=build GDUtils.py
+68 -24
View File
@@ -1,17 +1,13 @@
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QWidget, QLabel, QPushButton, QFileDialog, QInputDialog, QMessageBox, QCheckBox
from PyQt6.QtGui import QFont
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QWidget, QLabel, QPushButton, QFileDialog, QInputDialog, QMessageBox, QCheckBox
from PySide6.QtGui import QFont
from Crypto.Cipher import AES
import base64
import gzip
import zlib
import pyperclip
import hashlib
import platform
if platform.system() == "Windows":
from winmica import EnableMica, BackdropType, is_mica_supported
MAC_SAVE_KEY = (
b"\x69\x70\x75\x39\x54\x55\x76\x35\x34\x79\x76\x5d\x69\x73\x46\x4d"
@@ -98,7 +94,6 @@ class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("GDUtils")
self.apply_mica(self)
titleLabel = QLabel("GDUtils")
font = QFont()
@@ -136,6 +131,19 @@ class MainWindow(QMainWindow):
levelDataButtons.addWidget(self.levelDataIsOfficial, alignment=Qt.AlignmentFlag.AlignHCenter)
levelDataButtons.addStretch()
gdLvlGDShareLabel = QLabel("GDLVL/GDShare")
self.convertToGdLvl = QPushButton("Convert to GDLVL")
self.convertToGdLvl.clicked.connect(self.on_convert_from_gmd_click)
self.convertToGmd = QPushButton("Convert to GMD")
self.convertToGmd.clicked.connect(self.on_convert_from_gdlvl_click)
gdLvlGDShareButtons = QHBoxLayout()
gdLvlGDShareButtons.addStretch()
gdLvlGDShareButtons.addWidget(self.convertToGdLvl, alignment=Qt.AlignmentFlag.AlignHCenter)
gdLvlGDShareButtons.addWidget(self.convertToGmd, alignment=Qt.AlignmentFlag.AlignHCenter)
gdLvlGDShareButtons.addStretch()
gjpLabel = QLabel("GJP")
self.gjpDecode = QPushButton("Decode")
@@ -160,6 +168,8 @@ class MainWindow(QMainWindow):
layout.addLayout(saveFileButtons)
layout.addWidget(levelDataLabel, alignment=Qt.AlignmentFlag.AlignHCenter)
layout.addLayout(levelDataButtons)
layout.addWidget(gdLvlGDShareLabel, alignment=Qt.AlignmentFlag.AlignHCenter)
layout.addLayout(gdLvlGDShareButtons)
layout.addWidget(gjpLabel, alignment=Qt.AlignmentFlag.AlignHCenter)
layout.addLayout(gjpButtons)
layout.addWidget(gjp2Label, alignment=Qt.AlignmentFlag.AlignHCenter)
@@ -170,12 +180,6 @@ class MainWindow(QMainWindow):
container.setLayout(layout)
self.setCentralWidget(container)
def apply_mica(self, widget):
if platform.system() == "Windows" and is_mica_supported():
widget.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)
hwnd = int(widget.winId())
EnableMica(hwnd, BackdropType.MICA)
def on_save_decode_click(self):
file_path, _ = QFileDialog.getOpenFileName(
self,
@@ -237,7 +241,6 @@ class MainWindow(QMainWindow):
dialog = QInputDialog(self)
dialog.setWindowTitle("Level decoder")
dialog.setLabelText("Enter the level data to decode:")
self.apply_mica(dialog)
ok = dialog.exec()
data = dialog.textValue()
if ok and data:
@@ -245,14 +248,12 @@ class MainWindow(QMainWindow):
msg = QMessageBox()
msg.setWindowTitle("Level decoder")
msg.setText("The decoded level data has been copied to your clipboard")
self.apply_mica(msg)
msg.exec()
def on_level_encode_click(self):
dialog = QInputDialog(self)
dialog.setWindowTitle("Level encoder")
dialog.setLabelText("Enter the level data to encode:")
self.apply_mica(dialog)
ok = dialog.exec()
data = dialog.textValue()
if ok and data:
@@ -260,14 +261,62 @@ class MainWindow(QMainWindow):
msg = QMessageBox()
msg.setWindowTitle("Level encoder")
msg.setText("The encoded level data has been copied to your clipboard")
self.apply_mica(msg)
msg.exec()
def on_convert_from_gdlvl_click(self):
file_path, _ = QFileDialog.getOpenFileName(
self,
"Select a GDLVL file",
"",
"GDLVL Files (*.gdlvl)"
)
if not file_path:
return
output_file_path, _ = QFileDialog.getSaveFileName(
self,
"Select a location for the output GMD file",
file_path.removesuffix(".gdlvl") + ".gmd",
"GMD Files (*.gmd)"
)
if not output_file_path:
return
with open(file_path, "r") as f:
data = f.read()
with open(output_file_path, "w") as f:
f.write(decode_level(data, False))
def on_convert_from_gmd_click(self):
file_path, _ = QFileDialog.getOpenFileName(
self,
"Select a GMD file",
"",
"GMD Files (*.gmd)"
)
if not file_path:
return
output_file_path, _ = QFileDialog.getSaveFileName(
self,
"Select a location for the output GDLVL file",
file_path.removesuffix(".gmd") + ".gdlvl",
"GDLVL Files (*.gdlvl)"
)
if not output_file_path:
return
with open(file_path, "r") as f:
data = f.read()
with open(output_file_path, "w") as f:
f.write(encode_level(data, False))
def on_gjp_decode_click(self):
dialog = QInputDialog(self)
dialog.setWindowTitle("GJP decoder")
dialog.setLabelText("Enter the GJP to decode:")
self.apply_mica(dialog)
ok = dialog.exec()
data = dialog.textValue()
if ok and data:
@@ -275,14 +324,12 @@ class MainWindow(QMainWindow):
msg = QMessageBox()
msg.setWindowTitle("GJP decoder")
msg.setText("The decoded GJP has been copied to your clipboard")
self.apply_mica(msg)
msg.exec()
def on_gjp_encode_click(self):
dialog = QInputDialog(self)
dialog.setWindowTitle("GJP encoder")
dialog.setLabelText("Enter the password to encode:")
self.apply_mica(dialog)
ok = dialog.exec()
data = dialog.textValue()
if ok and data:
@@ -290,14 +337,12 @@ class MainWindow(QMainWindow):
msg = QMessageBox()
msg.setWindowTitle("GJP encoder")
msg.setText("The encoded GJP has been copied to your clipboard")
self.apply_mica(msg)
msg.exec()
def on_gjp2_encode_click(self):
dialog = QInputDialog(self)
dialog.setWindowTitle("GJP2 encoder")
dialog.setLabelText("Enter the password to encode:")
self.apply_mica(dialog)
ok = dialog.exec()
data = dialog.textValue()
if ok and data:
@@ -305,7 +350,6 @@ class MainWindow(QMainWindow):
msg = QMessageBox()
msg.setWindowTitle("GJP2 encoder")
msg.setText("The encoded GJP2 has been copied to your clipboard")
self.apply_mica(msg)
msg.exec()
app = QApplication(sys.argv)
+8 -4
View File
@@ -9,10 +9,14 @@ A simple python utility app for things related to Geometry Dash
- GJP encode/decode
- GJP2 encode
## Setup
## Download
Download the latest release for your platform [here](https://git.lncvrt.xyz/Lncvrt/gdutils/releases)
## Run manually with Python
[Download the repository as a ZIP](https://git.lncvrt.xyz/Lncvrt/gdutils/archive/main.zip) and unzip it then run:
`pip install -r requirements.txt` (you may need to replace pip with pip3)
then run
`python app.py` (you may need to replace python with python3)
`pip install -r requirements.txt` then run `python GDUtils.py`
(you may need to replace pip and python with pip3 and python3)
+1 -2
View File
@@ -1,4 +1,3 @@
PyQt6
pyside6
pycryptodome
pyperclip
winmica ; sys_platform == 'win32'