Blacksite/scripts/editor/blacksite-editor

185 lines
5.6 KiB
Bash
Executable File

#!/usr/bin/env bash
set -u
readonly REPO="/home/Rbanh/Documents/Bevy"
readonly TARGET_DIR="$REPO/target"
readonly EDITOR_BINARY="$TARGET_DIR/debug/editor"
readonly LAUNCHER_BINARY="$TARGET_DIR/debug/project_launcher"
readonly STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/blacksite-editor"
readonly LOG_FILE="$STATE_DIR/launch.log"
readonly STATUS_FILE="$STATE_DIR/splash.status"
readonly SPLASH="$REPO/scripts/editor/splash.py"
readonly CARGO_LANE="$REPO/scripts/codex/cargo_lane.py"
build_only=false
project_browser=false
gpu_validation=0
sdr_fallback=false
splash_pid=""
keep_splash=false
case "${1:-}" in
--build-only) build_only=true ;;
--launcher) project_browser=true ;;
--gpu-validation) gpu_validation=1 ;;
--sdr) sdr_fallback=true ;;
"") ;;
*)
printf 'Unknown option: %s\n' "$1" >&2
exit 2
;;
esac
if $project_browser; then
binary="$LAUNCHER_BINARY"
process_name="project_launcher"
service_description="Blacksite Project Browser"
else
binary="$EDITOR_BINARY"
process_name="editor"
service_description="Blacksite Editor"
fi
if ! $build_only && [[ "${BLACKSITE_EDITOR_SERVICE:-0}" != 1 ]]; then
service_environment=(--setenv=BLACKSITE_EDITOR_SERVICE=1 --setenv=PATH)
for variable in \
WAYLAND_DISPLAY DISPLAY XAUTHORITY XDG_RUNTIME_DIR \
HYPRLAND_INSTANCE_SIGNATURE DBUS_SESSION_BUS_ADDRESS \
XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP XDG_SESSION_TYPE \
XDG_DATA_HOME XDG_CONFIG_HOME XDG_STATE_HOME GDK_BACKEND; do
if [[ -v "$variable" ]]; then
service_environment+=(--setenv="$variable")
fi
done
launcher_arguments=()
[[ $# -gt 0 ]] && launcher_arguments+=("$1")
exec systemd-run --user --collect --quiet --service-type=exec \
--description="$service_description" \
"${service_environment[@]}" \
"$0" "${launcher_arguments[@]}"
fi
write_status() {
local phase="$1"
local detail="$2"
local progress="$3"
local state="${4:-running}"
local crate_count="${5:-}"
printf '%s\n%s\n%s\n%s\n%s\n' \
"$phase" "$detail" "$progress" "$state" "$crate_count" >"$STATUS_FILE.tmp"
mv "$STATUS_FILE.tmp" "$STATUS_FILE"
}
close_splash() {
if [[ -n "$splash_pid" ]] && ! $keep_splash; then
write_status "Editor ready" "Opening workspace" 100 close
fi
}
trap close_splash EXIT
focus_existing() {
local pid executable
while read -r pid; do
[[ -n "$pid" ]] || continue
executable="$(readlink -f "/proc/$pid/exe" 2>/dev/null || true)"
if [[ "$executable" == "$binary" ]]; then
if command -v hyprctl >/dev/null 2>&1; then
hyprctl dispatch focuswindow "pid:$pid" >/dev/null 2>&1 || true
fi
return 0
fi
done < <(pgrep -x "$process_name" 2>/dev/null || true)
return 1
}
if ! $build_only && focus_existing; then
exit 0
fi
mkdir -p "$STATE_DIR"
exec 9>"$STATE_DIR/launch.lock"
if ! flock -n 9; then
exit 0
fi
: >"$LOG_FILE"
write_status "Preparing workspace" "Reading project configuration" 5
if ! $build_only; then
GSK_RENDERER=gl python3 "$SPLASH" "$STATUS_FILE" "$LOG_FILE" &
splash_pid=$!
fi
if ! cd "$REPO"; then
write_status "Project unavailable" "$REPO could not be opened" 100 error
keep_splash=true
exit 1
fi
if $build_only; then
exec python3 "$CARGO_LANE" exec dev -- cargo build -p editor --bin editor
fi
if [[ ! -x "$binary" ]]; then
write_status "Editor build unavailable" \
"Run blacksite-editor --build-only from a terminal" 100 error
keep_splash=true
exit 1
fi
export RUST_BACKTRACE=1
export WGPU_VALIDATION="$gpu_validation"
if $sdr_fallback; then
export BEVY_FPS_HDR=0
fi
export LD_LIBRARY_PATH="$TARGET_DIR/debug/deps${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
write_status "Starting editor" "Opening the current development build" 82
watch_editor_window() {
local editor_pid="$1"
trap - EXIT
if command -v hyprctl >/dev/null 2>&1 && command -v jq >/dev/null 2>&1; then
for ((attempt = 0; attempt < 300; attempt++)); do
if ! kill -0 "$editor_pid" 2>/dev/null; then
write_status "Editor stopped during startup" \
"Open the launch log for runtime details" 100 error
return
fi
if hyprctl clients -j 2>/dev/null | jq -e --argjson pid "$editor_pid" \
'any(.[]; .pid == $pid and .mapped == true)' >/dev/null; then
write_status "Editor ready" "Opening workspace" 100
sleep 0.4
write_status "Editor ready" "Opening workspace" 100 close
return
fi
if ((attempt == 10)); then
write_status "Initializing renderer" "Connecting to the graphics device" 88
elif ((attempt == 35)); then
write_status "Loading editor scene" "Preparing the workspace" 94
fi
sleep 0.1
done
else
write_status "Loading editor scene" "Preparing the workspace" 94
sleep 5
if kill -0 "$editor_pid" 2>/dev/null; then
write_status "Editor ready" "Opening workspace" 100
sleep 0.4
write_status "Editor ready" "Opening workspace" 100 close
return
fi
fi
write_status "Editor is taking longer than expected" \
"The process is still running; check the launch log" 100 error
}
watch_editor_window "$$" &
exec "$binary" >>"$LOG_FILE" 2>&1
write_status "Editor could not be started" \
"Open the launch log for runtime details" 100 error
keep_splash=true
exit 1