Compare commits

..
1 Commits
Author SHA1 Message Date
Lncvrt 97e5f4ac06 GDLVL/GMD conversion support 2026-10-20 17:22:55 -07:00
5 changed files with 36 additions and 32 deletions

No files matched your search

-2
View File
@@ -1,2 +0,0 @@
.DS_Store
build/
-12
View File
@@ -1,12 +0,0 @@
# 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
+4 -8
View File
@@ -9,14 +9,10 @@ A simple python utility app for things related to Geometry Dash
- GJP encode/decode - GJP encode/decode
- GJP2 encode - GJP2 encode
## Download ## Setup
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: [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` then run `python GDUtils.py` `pip install -r requirements.txt` (you may need to replace pip with pip3)
then run
(you may need to replace pip and python with pip3 and python3) `python app.py` (you may need to replace python with python3)
+30 -9
View File
@@ -1,13 +1,17 @@
import sys import sys
from PySide6.QtCore import Qt from PyQt6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QWidget, QLabel, QPushButton, QFileDialog, QInputDialog, QMessageBox, QCheckBox from PyQt6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QWidget, QLabel, QPushButton, QFileDialog, QInputDialog, QMessageBox, QCheckBox
from PySide6.QtGui import QFont from PyQt6.QtGui import QFont
from Crypto.Cipher import AES from Crypto.Cipher import AES
import base64 import base64
import gzip import gzip
import zlib import zlib
import pyperclip import pyperclip
import hashlib import hashlib
import platform
if platform.system() == "Windows":
from winmica import EnableMica, BackdropType, is_mica_supported
MAC_SAVE_KEY = ( MAC_SAVE_KEY = (
b"\x69\x70\x75\x39\x54\x55\x76\x35\x34\x79\x76\x5d\x69\x73\x46\x4d" b"\x69\x70\x75\x39\x54\x55\x76\x35\x34\x79\x76\x5d\x69\x73\x46\x4d"
@@ -94,6 +98,7 @@ class MainWindow(QMainWindow):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.setWindowTitle("GDUtils") self.setWindowTitle("GDUtils")
self.apply_mica(self)
titleLabel = QLabel("GDUtils") titleLabel = QLabel("GDUtils")
font = QFont() font = QFont()
@@ -134,9 +139,9 @@ class MainWindow(QMainWindow):
gdLvlGDShareLabel = QLabel("GDLVL/GDShare") gdLvlGDShareLabel = QLabel("GDLVL/GDShare")
self.convertToGdLvl = QPushButton("Convert to GDLVL") self.convertToGdLvl = QPushButton("Convert to GDLVL")
self.convertToGdLvl.clicked.connect(self.on_convert_from_gmd_click) self.convertToGdLvl.clicked.connect(self.on_convert_to_gdlvl_click)
self.convertToGmd = QPushButton("Convert to GMD") self.convertToGmd = QPushButton("Convert to GMD")
self.convertToGmd.clicked.connect(self.on_convert_from_gdlvl_click) self.convertToGmd.clicked.connect(self.on_convert_to_gmd_click)
gdLvlGDShareButtons = QHBoxLayout() gdLvlGDShareButtons = QHBoxLayout()
gdLvlGDShareButtons.addStretch() gdLvlGDShareButtons.addStretch()
@@ -180,6 +185,12 @@ class MainWindow(QMainWindow):
container.setLayout(layout) container.setLayout(layout)
self.setCentralWidget(container) 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): def on_save_decode_click(self):
file_path, _ = QFileDialog.getOpenFileName( file_path, _ = QFileDialog.getOpenFileName(
self, self,
@@ -241,6 +252,7 @@ class MainWindow(QMainWindow):
dialog = QInputDialog(self) dialog = QInputDialog(self)
dialog.setWindowTitle("Level decoder") dialog.setWindowTitle("Level decoder")
dialog.setLabelText("Enter the level data to decode:") dialog.setLabelText("Enter the level data to decode:")
self.apply_mica(dialog)
ok = dialog.exec() ok = dialog.exec()
data = dialog.textValue() data = dialog.textValue()
if ok and data: if ok and data:
@@ -248,12 +260,14 @@ class MainWindow(QMainWindow):
msg = QMessageBox() msg = QMessageBox()
msg.setWindowTitle("Level decoder") msg.setWindowTitle("Level decoder")
msg.setText("The decoded level data has been copied to your clipboard") msg.setText("The decoded level data has been copied to your clipboard")
self.apply_mica(msg)
msg.exec() msg.exec()
def on_level_encode_click(self): def on_level_encode_click(self):
dialog = QInputDialog(self) dialog = QInputDialog(self)
dialog.setWindowTitle("Level encoder") dialog.setWindowTitle("Level encoder")
dialog.setLabelText("Enter the level data to encode:") dialog.setLabelText("Enter the level data to encode:")
self.apply_mica(dialog)
ok = dialog.exec() ok = dialog.exec()
data = dialog.textValue() data = dialog.textValue()
if ok and data: if ok and data:
@@ -261,9 +275,10 @@ class MainWindow(QMainWindow):
msg = QMessageBox() msg = QMessageBox()
msg.setWindowTitle("Level encoder") msg.setWindowTitle("Level encoder")
msg.setText("The encoded level data has been copied to your clipboard") msg.setText("The encoded level data has been copied to your clipboard")
self.apply_mica(msg)
msg.exec() msg.exec()
def on_convert_from_gdlvl_click(self): def on_convert_to_gdlvl_click(self):
file_path, _ = QFileDialog.getOpenFileName( file_path, _ = QFileDialog.getOpenFileName(
self, self,
"Select a GDLVL file", "Select a GDLVL file",
@@ -286,9 +301,9 @@ class MainWindow(QMainWindow):
data = f.read() data = f.read()
with open(output_file_path, "w") as f: with open(output_file_path, "w") as f:
f.write(decode_level(data, False)) f.write(decode_level(data, is_official_level=False))
def on_convert_from_gmd_click(self): def on_convert_to_gmd_click(self):
file_path, _ = QFileDialog.getOpenFileName( file_path, _ = QFileDialog.getOpenFileName(
self, self,
"Select a GMD file", "Select a GMD file",
@@ -311,12 +326,13 @@ class MainWindow(QMainWindow):
data = f.read() data = f.read()
with open(output_file_path, "w") as f: with open(output_file_path, "w") as f:
f.write(encode_level(data, False)) f.write(encode_level(data, is_official_level=False))
def on_gjp_decode_click(self): def on_gjp_decode_click(self):
dialog = QInputDialog(self) dialog = QInputDialog(self)
dialog.setWindowTitle("GJP decoder") dialog.setWindowTitle("GJP decoder")
dialog.setLabelText("Enter the GJP to decode:") dialog.setLabelText("Enter the GJP to decode:")
self.apply_mica(dialog)
ok = dialog.exec() ok = dialog.exec()
data = dialog.textValue() data = dialog.textValue()
if ok and data: if ok and data:
@@ -324,12 +340,14 @@ class MainWindow(QMainWindow):
msg = QMessageBox() msg = QMessageBox()
msg.setWindowTitle("GJP decoder") msg.setWindowTitle("GJP decoder")
msg.setText("The decoded GJP has been copied to your clipboard") msg.setText("The decoded GJP has been copied to your clipboard")
self.apply_mica(msg)
msg.exec() msg.exec()
def on_gjp_encode_click(self): def on_gjp_encode_click(self):
dialog = QInputDialog(self) dialog = QInputDialog(self)
dialog.setWindowTitle("GJP encoder") dialog.setWindowTitle("GJP encoder")
dialog.setLabelText("Enter the password to encode:") dialog.setLabelText("Enter the password to encode:")
self.apply_mica(dialog)
ok = dialog.exec() ok = dialog.exec()
data = dialog.textValue() data = dialog.textValue()
if ok and data: if ok and data:
@@ -337,12 +355,14 @@ class MainWindow(QMainWindow):
msg = QMessageBox() msg = QMessageBox()
msg.setWindowTitle("GJP encoder") msg.setWindowTitle("GJP encoder")
msg.setText("The encoded GJP has been copied to your clipboard") msg.setText("The encoded GJP has been copied to your clipboard")
self.apply_mica(msg)
msg.exec() msg.exec()
def on_gjp2_encode_click(self): def on_gjp2_encode_click(self):
dialog = QInputDialog(self) dialog = QInputDialog(self)
dialog.setWindowTitle("GJP2 encoder") dialog.setWindowTitle("GJP2 encoder")
dialog.setLabelText("Enter the password to encode:") dialog.setLabelText("Enter the password to encode:")
self.apply_mica(dialog)
ok = dialog.exec() ok = dialog.exec()
data = dialog.textValue() data = dialog.textValue()
if ok and data: if ok and data:
@@ -350,6 +370,7 @@ class MainWindow(QMainWindow):
msg = QMessageBox() msg = QMessageBox()
msg.setWindowTitle("GJP2 encoder") msg.setWindowTitle("GJP2 encoder")
msg.setText("The encoded GJP2 has been copied to your clipboard") msg.setText("The encoded GJP2 has been copied to your clipboard")
self.apply_mica(msg)
msg.exec() msg.exec()
app = QApplication(sys.argv) app = QApplication(sys.argv)
+2 -1
View File
@@ -1,3 +1,4 @@
pyside6 PyQt6
pycryptodome pycryptodome
pyperclip pyperclip
winmica ; sys_platform == 'win32'