Fix NSIS installer build: absolute paths via defines, space-free installed exe, BMP ICO
- makensis resolves relative -DICON/-DARTIFACT against the script directory, so CI now passes $PWD-based absolute paths (reproduced locally in the same ubuntu:24.04 container; installer builds, 7z shows step-line.exe + uninstall.exe) - Install as step-line.exe (no spaces: NSIS /oname splits on whitespace) - OutFile overridable via -DOUT - tools/generate_textures.py icon.ico now produced via ImageMagick with classic BMP entries (NSIS-compatible); PIL PNG-compressed ICOs rejected by NSIS
No files matched your search
@@ -82,19 +82,21 @@ jobs:
|
||||
sudo apt-get update && sudo apt-get install -y nsis p7zip-full
|
||||
VERSION="$(sed -n 's/.*config\/version="\([^"]*\)".*/\1/p' project.godot)"
|
||||
# NOTE: on Linux, makensis uses -D defines (the /D form is Windows-only
|
||||
# and is rejected as a script path).
|
||||
# and is rejected as a script path), and it resolves relative paths
|
||||
# against the script directory — pass absolute paths from the workspace.
|
||||
cp assets/textures/icon.ico packaging/windows/step-line.ico
|
||||
makensis \
|
||||
-DVERSION="$VERSION" \
|
||||
-DARTIFACT="build/step-line-windows-$VERSION.exe" \
|
||||
-DICON=packaging/windows/step-line.ico \
|
||||
-DARTIFACT="$PWD/build/step-line-windows-$VERSION.exe" \
|
||||
-DICON="$PWD/packaging/windows/step-line.ico" \
|
||||
-DOUT="$PWD/build/step-line-setup-$VERSION.exe" \
|
||||
packaging/windows/step-line.nsi
|
||||
|
||||
- name: Verify Windows installer contents
|
||||
run: |
|
||||
VERSION="$(sed -n 's/.*config\/version="\([^"]*\)".*/\1/p' project.godot)"
|
||||
ls -la build/step-line-setup-$VERSION.exe
|
||||
7z l build/step-line-setup-$VERSION.exe | grep -E "Step Line.exe|uninstall.exe"
|
||||
7z l build/step-line-setup-$VERSION.exe | grep -E "step-line.exe|uninstall.exe"
|
||||
|
||||
- name: Package Linux AppImage
|
||||
run: |
|
||||
|
||||
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 225 KiB After Width: | Height: | Size: 191 KiB |
|
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 197 KiB |
|
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 214 KiB |
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 200 KiB |
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 237 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 15 KiB |
@@ -14,8 +14,12 @@
|
||||
!define ICON "packaging\windows\step-line.ico"
|
||||
!endif
|
||||
|
||||
; The installed executable always uses this clean name.
|
||||
!define INSTALLED_EXE "Step Line.exe"
|
||||
; The installed executable uses this clean name (no spaces — NSIS /oname tokens
|
||||
; on whitespace, so a spaced name breaks the File directive).
|
||||
!define INSTALLED_EXE "step-line.exe"
|
||||
!ifndef OUT
|
||||
!define OUT "build\step-line-setup-${VERSION}.exe"
|
||||
!endif
|
||||
!define COMPANY "Step Line Project"
|
||||
!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\Step Line"
|
||||
|
||||
@@ -25,7 +29,7 @@ Icon "${ICON}"
|
||||
UninstallIcon "${ICON}"
|
||||
|
||||
Name "Step Line ${VERSION}"
|
||||
OutFile "build\step-line-setup-${VERSION}.exe"
|
||||
OutFile "${OUT}"
|
||||
InstallDir "$PROGRAMFILES64\Step Line"
|
||||
RequestExecutionLevel admin
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ func _init() -> void:
|
||||
# --- body-camera overlay (REC + shift clock + corner brackets, top right) ---
|
||||
var cam_box := VBoxContainer.new()
|
||||
cam_box.set_anchors_preset(Control.PRESET_TOP_RIGHT)
|
||||
cam_box.position = Vector2(-180, 12)
|
||||
cam_box.position = Vector2(-180, 50)
|
||||
cam_box.alignment = BoxContainer.ALIGNMENT_END
|
||||
add_child(cam_box)
|
||||
var rec_row := HBoxContainer.new()
|
||||
@@ -380,6 +380,7 @@ func show_inspection(controller: Object, artifacts: Array, result: Dictionary) -
|
||||
continue
|
||||
var card := TextureRect.new()
|
||||
card.texture = tex
|
||||
card.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||
card.custom_minimum_size = Vector2(92, 58)
|
||||
card.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
||||
card.tooltip_text = artifact.summary()
|
||||
@@ -388,7 +389,8 @@ func show_inspection(controller: Object, artifacts: Array, result: Dictionary) -
|
||||
card_row.add_child(card)
|
||||
added_card = true
|
||||
if added_card:
|
||||
inspect_panel.add_child(card_row)
|
||||
var content := inspect_panel.get_child(0) as VBoxContainer
|
||||
content.add_child(card_row)
|
||||
var lines: Array[String] = []
|
||||
for artifact in artifacts:
|
||||
lines.append(" • " + artifact.summary())
|
||||
@@ -409,7 +411,7 @@ func _clear_card_row() -> void:
|
||||
return
|
||||
var row := inspect_panel.find_child("INSPECT_CARD_ROW", true, false) as Control
|
||||
if row:
|
||||
inspect_panel.remove_child(row)
|
||||
row.get_parent().remove_child(row)
|
||||
row.queue_free()
|
||||
|
||||
func show_wand(controller: Object, result: Dictionary) -> void:
|
||||
|
||||
@@ -306,12 +306,30 @@ def app_icon():
|
||||
icon("icon.png", badge, size=1024)
|
||||
icon("icon.ico", badge, size=256)
|
||||
|
||||
# ICO for Windows. Sizes stay at 16/32/48 so every entry uses classic BMP
|
||||
# (PNG-compressed entries, used by PIL at >=256px, break some NSIS builds).
|
||||
src = Image.open(os.path.join(ASSETS, "icon.png")).convert("RGBA")
|
||||
# ICO for Windows. Must be BMP-entry based: PIL's ICO serializer emits
|
||||
# PNG-compressed entries which NSIS' icon loader rejects. ImageMagick
|
||||
# writes classic BMP entries; fall back to PIL only if ImageMagick is gone
|
||||
# (flag it so a human notices).
|
||||
import subprocess
|
||||
import sys
|
||||
ico_path = os.path.join(ASSETS, "icon.ico")
|
||||
src.save(ico_path, format="ICO", sizes=[(48, 48), (32, 32), (16, 16)])
|
||||
print("wrote assets/textures/icon.ico (BMP 16/32/48)")
|
||||
src_png = os.path.join(ASSETS, "icon.png")
|
||||
ran = False
|
||||
for cmd in (
|
||||
["magick", src_png, "-background", "none", "-define", "icon:auto-resize=48,32,16", ico_path],
|
||||
["convert", src_png, "-background", "none", "-define", "icon:auto-resize=48,32,16", ico_path],
|
||||
):
|
||||
try:
|
||||
subprocess.run(cmd, check=True, capture_output=True)
|
||||
ran = True
|
||||
break
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
continue
|
||||
if ran:
|
||||
print("wrote assets/textures/icon.ico (BMP 16/32/48 via ImageMagick)")
|
||||
else:
|
||||
print("WARNING: ImageMagick not found; writing PIL ICO (may be PNG-compressed)")
|
||||
Image.open(src_png).convert("RGBA").save(ico_path, format="ICO", sizes=[(48, 48), (32, 32), (16, 16)])
|
||||
|
||||
|
||||
def cards():
|
||||
|
||||