From 10e9e7b2a4d3d44c2a641b89ca13e6d8c58e0110 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 5 Oct 2026 22:48:25 +0200 Subject: [PATCH] New app icon, packaged with a menu entry for Linux The icon is a plate wearing headphones with a red Nordic house cookie on it. It replaces the default Godot icon, so the game window, Windows and macOS builds use it. Linux programs can't carry their own icon, so the build now also makes MusicPlayer__linux.tar.gz with the game, the icon as a PNG, a .desktop menu entry and install.sh, which installs them for the current user. The bare Linux binary is still published. --- .gitea/workflows/gitea-build.yaml | 5 ++ RELEASING.md | 11 ++- export_presets.cfg | 8 +- icon.svg | 117 +++++++++++++++++++++++++- icon.svg.import | 6 ++ linux/install.sh | 30 +++++++ linux/music-player-randomizer.desktop | 8 ++ linux/package.sh | 35 ++++++++ linux/render_icon.gd | 24 ++++++ linux/render_icon.gd.uid | 1 + 10 files changed, 239 insertions(+), 6 deletions(-) create mode 100755 linux/install.sh create mode 100644 linux/music-player-randomizer.desktop create mode 100755 linux/package.sh create mode 100644 linux/render_icon.gd create mode 100644 linux/render_icon.gd.uid diff --git a/.gitea/workflows/gitea-build.yaml b/.gitea/workflows/gitea-build.yaml index f94ed3b..dda2fd5 100644 --- a/.gitea/workflows/gitea-build.yaml +++ b/.gitea/workflows/gitea-build.yaml @@ -83,6 +83,11 @@ jobs: godot --headless --path . --import godot --headless --path . --export-release "Windows Desktop" "build/${PROJECT_NAME}_${GAME_VERSION}.exe" godot --headless --path . --export-release "Linux" "build/${PROJECT_NAME}_${GAME_VERSION}.x86_64" + + # Linux binaries can't hold an icon; the package adds it with a menu entry and installer + - name: Package Linux + run: | + linux/package.sh "build/${PROJECT_NAME}_${GAME_VERSION}.x86_64" "$GAME_VERSION" build ls -la build - name: Upload Artifacts diff --git a/RELEASING.md b/RELEASING.md index d043822..e142d53 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -11,10 +11,19 @@ same version in the About window. The `Build` workflow (`.gitea/workflows/gitea-build.yaml`) then: 1. runs the tests, -2. exports the Windows and Linux builds, +2. exports the Windows and Linux builds, and packages Linux as + `MusicPlayer__linux.tar.gz` with the icon, an app menu entry and `install.sh` + (Linux programs can't carry their own icon the way a Windows .exe does), 3. if no tag exists for the version yet: uploads the builds to the package registry under `MusicPlayer//`, and creates the `` tag and Gitea release with the builds attached. Pushes that don't change the version, and pushes to `develop`, only test and export. Don't create tags or `1.x.y` branches by hand; the workflow makes the tag. + +## Installing on Linux + +Unpack `MusicPlayer__linux.tar.gz` and run `./install.sh` inside the +`MusicPlayer` folder. It installs the game to `~/.local/bin` and adds it, with its icon, +to the app menu. The bare `MusicPlayer_.x86_64` is still published for anyone +who just wants to run the file. diff --git a/export_presets.cfg b/export_presets.cfg index b3391b5..86ddd90 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -8,7 +8,7 @@ dedicated_server=false custom_features="" export_filter="all_resources" include_filter="" -exclude_filter="tests/*, addons/gdUnit4/*" +exclude_filter="tests/*, addons/gdUnit4/*, linux/*" export_path="../../MusicPlayer_1.5.1.exe" patches=PackedStringArray() encryption_include_filters="" @@ -83,7 +83,7 @@ dedicated_server=false custom_features="" export_filter="all_resources" include_filter="" -exclude_filter="tests/*, addons/gdUnit4/*" +exclude_filter="tests/*, addons/gdUnit4/*, linux/*" export_path="./MusicPlayer_0.9_Beta.dmg" patches=PackedStringArray() encryption_include_filters="" @@ -343,7 +343,7 @@ dedicated_server=false custom_features="" export_filter="all_resources" include_filter="" -exclude_filter="tests/*, addons/gdUnit4/*" +exclude_filter="tests/*, addons/gdUnit4/*, linux/*" export_path="web/index.html" patches=PackedStringArray() encryption_include_filters="" @@ -390,7 +390,7 @@ dedicated_server=false custom_features="" export_filter="all_resources" include_filter="" -exclude_filter="tests/*, addons/gdUnit4/*" +exclude_filter="tests/*, addons/gdUnit4/*, linux/*" export_path="./MusicPlayer_1.5.1.x86_64" patches=PackedStringArray() encryption_include_filters="" diff --git a/icon.svg b/icon.svg index adc26df..c60f5f1 100644 --- a/icon.svg +++ b/icon.svg @@ -1 +1,116 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icon.svg.import b/icon.svg.import index 187e4e3..b43d438 100644 --- a/icon.svg.import +++ b/icon.svg.import @@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.cte compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 @@ -25,6 +27,10 @@ mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 process/fix_alpha_border=true process/premult_alpha=false process/normal_map_invert_y=false diff --git a/linux/install.sh b/linux/install.sh new file mode 100755 index 0000000..b249216 --- /dev/null +++ b/linux/install.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Installs Music Player Randomizer for the current user, with an app menu entry and icon. +# Run it from the unpacked release folder: ./install.sh + +set -euo pipefail +cd "$(dirname "$0")" + +bin_dir="${XDG_BIN_HOME:-$HOME/.local/bin}" +data_dir="${XDG_DATA_HOME:-$HOME/.local/share}" +binary="$bin_dir/music-player-randomizer" + +icon_dir="$data_dir/icons/hicolor/256x256/apps" +mkdir -p "$bin_dir" "$icon_dir" "$data_dir/applications" +install -m755 MusicPlayer.x86_64 "$binary" +install -m644 music-player-randomizer.png "$icon_dir/music-player-randomizer.png" +# The menu entry needs the full path, since ~/.local/bin is not always on PATH +sed "s|^Exec=.*|Exec=$binary|" music-player-randomizer.desktop \ + > "$data_dir/applications/music-player-randomizer.desktop" + +# Refresh menu and icon caches where the tools exist; most desktops also notice on their own +command -v update-desktop-database > /dev/null \ + && update-desktop-database "$data_dir/applications" || true +command -v gtk-update-icon-cache > /dev/null \ + && gtk-update-icon-cache -q "$data_dir/icons/hicolor" || true + +echo "Installed. Start it from your app menu, or run: $binary" +echo "To uninstall, delete:" +echo " $binary" +echo " $data_dir/applications/music-player-randomizer.desktop" +echo " $icon_dir/music-player-randomizer.png" diff --git a/linux/music-player-randomizer.desktop b/linux/music-player-randomizer.desktop new file mode 100644 index 0000000..911aa4d --- /dev/null +++ b/linux/music-player-randomizer.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Application +Name=Music Player Randomizer +Comment=Guess the video game soundtrack with your friends +Exec=music-player-randomizer +Icon=music-player-randomizer +Terminal=false +Categories=Game;Audio; diff --git a/linux/package.sh b/linux/package.sh new file mode 100755 index 0000000..934c720 --- /dev/null +++ b/linux/package.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# Packages an exported Linux build with its icon, app menu entry and install script. +# +# Usage: linux/package.sh +# Creates /MusicPlayer__linux.tar.gz. Godot is taken from $GODOT, +# or `godot` on PATH, to render the icon. + +set -euo pipefail + +if [[ $# -ne 3 ]]; then + echo "Usage: $0 " >&2 + exit 1 +fi +binary="$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" +version="$2" +out_dir="$(mkdir -p "$3" && cd "$3" && pwd)" +linux_dir="$(cd "$(dirname "$0")" && pwd)" +project_dir="$(dirname "$linux_dir")" +godot_bin="${GODOT:-godot}" + +staging="$(mktemp -d)" +trap 'rm -rf "$staging"' EXIT +package_dir="$staging/MusicPlayer" +mkdir -p "$package_dir" + +install -m755 "$binary" "$package_dir/MusicPlayer.x86_64" +install -m755 "$linux_dir/install.sh" "$package_dir/install.sh" +install -m644 "$linux_dir/music-player-randomizer.desktop" "$package_dir/" +# Run outside the project so Godot only renders the icon +(cd "$staging" && "$godot_bin" --headless -s "$linux_dir/render_icon.gd" -- \ + "$project_dir/icon.svg" "$package_dir/music-player-randomizer.png" 256) + +archive="$out_dir/MusicPlayer_${version}_linux.tar.gz" +tar -czf "$archive" -C "$staging" MusicPlayer +echo "Created $archive" diff --git a/linux/render_icon.gd b/linux/render_icon.gd new file mode 100644 index 0000000..ceab257 --- /dev/null +++ b/linux/render_icon.gd @@ -0,0 +1,24 @@ +extends SceneTree +## Renders an SVG to a square PNG, used to package the icon for Linux. +## +## Usage: godot --headless -s render_icon.gd -- + + +func _initialize() -> void: + var args: PackedStringArray = OS.get_cmdline_user_args() + if args.size() != 3: + printerr("Usage: godot --headless -s render_icon.gd -- ") + quit(1) + return + var svg: String = FileAccess.get_file_as_string(args[0]) + var source: Image = Image.new() + # Load at 1x to read the SVG's own size, then scale so the result is pixels + var error: int = source.load_svg_from_string(svg) + if error == OK: + var image: Image = Image.new() + error = image.load_svg_from_string(svg, float(args[2]) / source.get_width()) + if error == OK: + error = image.save_png(args[1]) + if error != OK: + printerr("Could not render %s to %s (error %d)" % [args[0], args[1], error]) + quit(error) diff --git a/linux/render_icon.gd.uid b/linux/render_icon.gd.uid new file mode 100644 index 0000000..ee4934c --- /dev/null +++ b/linux/render_icon.gd.uid @@ -0,0 +1 @@ +uid://b51oybupn7ns7