resetting repo

This commit is contained in:
2025-08-13 22:58:22 +02:00
parent b0af31800c
commit b160a7dc6e
4943 changed files with 14607 additions and 2100 deletions

24
.gitattributes vendored
View File

@@ -2,14 +2,32 @@
*.exe filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.JPG filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.PNG filter=lfs diff=lfs merge=lfs -text
*.pnG filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.webp filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
*.xcf filter=lfs diff=lfs merge=lfs -text
*.pxr filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.WAV filter=lfs diff=lfs merge=lfs -text
*.wav123321321 filter=lfs diff=lfs merge=lfs -text
*.sfk filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.rar filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.otf filter=lfs diff=lfs merge=lfs -text
*.lnk filter=lfs diff=lfs merge=lfs -text
*.pk filter=lfs diff=lfs merge=lfs -text
*.fig filter=lfs diff=lfs merge=lfs -text
*.fds filter=lfs diff=lfs merge=lfs -text
*.pdn filter=lfs diff=lfs merge=lfs -text
*.osk filter=lfs diff=lfs merge=lfs -text
*.osr filter=lfs diff=lfs merge=lfs -text
*.osz filter=lfs diff=lfs merge=lfs -text
*.pack filter=lfs diff=lfs merge=lfs -text
*.pdn filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.WAV filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text

View File

@@ -1,9 +1,7 @@
name: CI/CD Pipeline
name: Generate Skin previews, OSK files and per skin documentation
on:
push:
branches:
- main
paths:
- '.gitea/workflows/*'
- 'Skins/**/*'
@@ -25,22 +23,26 @@ env:
DANSER_SCREENSHOT_DIR: "/app/danser/screenshots"
SKINS_DIR: "${{ github.workspace }}/Skins"
DANSER_SKINS_DIR: "/app/danser/skins"
DEFAULT_SKIN_DIR: "${{ github.workspace }}/src/default-skin"
DEFAULT_SKIN_DIR: "/app/danser/skins/default-skin"
REPO_SCREENSHOT_DIR: "${{ github.workspace }}/media/gameplay"
REPO_MOD_ICONS_DIR: "${{ github.workspace }}/media/icons"
REPO_RANKING_PANEL_DIR: "${{ github.workspace }}/media/panel"
REPO_THUMBNAIL_DIR: "${{ github.workspace }}/media/thumbnail"
SETTINGS_JSON_PATH: "/app/danser/settings/default.json"
README_PATH: "${{ github.workspace }}/README.md"
REPLAY_PATH: "${{ github.workspace }}/src/replay.osr"
GAMEPLAY_REPLAY_PATH: "/app/danser/custom-replays/yomi_yori.osr"
THUMBNAIL_REPLAY_PATH: "/app/danser/custom-replays/combo_colors.osr"
PANEL_REPLAY_PATH: "/app/danser/custom-replays/2000_gekis.osr"
OSK_PATH: "${{ github.workspace }}/export"
IMAGE_NAME: osc/skins-image
REGISTRY_URL: "https://${{ vars.CONTAINER_REGISTRY }}"
OSU_ID: ${{ vars.OSUID }}
DOC_DIR: "${{ github.workspace }}/docs"
jobs:
generate_everything:
name: Full CI/CD Pipeline
runs-on: ubuntu-latest
runs-on: danser
container:
image: ${{ vars.CONTAINER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
options: >-
@@ -101,8 +103,8 @@ jobs:
echo "→ Target skins specified. Using target_skins input…"
IFS=',' read -r -a input_skins <<< "$target_skins"
for s in "${input_skins[@]}"; do
s="${s#"${s%%[![:space:]]*}"}" # trim leading whitespace
s="${s%"${s##*[![:space:]]}"}" # trim trailing whitespace
s="${s#"${s%%[![:space:]]*}"}"
s="${s%"${s##*[![:space:]]}"}"
[[ -n "$s" ]] && skins+=("$s")
done
echo " ✓ Found ${#skins[@]} skin(s) from target_skins input"
@@ -119,7 +121,7 @@ jobs:
git diff --name-only -z --diff-filter=AM "$latest_tag" HEAD \
| while IFS= read -r -d '' file; do
[[ $file == Skins/* ]] && echo "${file#Skins/}" | cut -d/ -f1
done
done | sort -u
)
echo " ✓ Found ${#skins[@]} added/modified skins"
@@ -128,7 +130,7 @@ jobs:
git diff --name-only -z --diff-filter=D "$latest_tag" HEAD \
| while IFS= read -r -d '' file; do
[[ $file == Skins/* ]] && echo "${file#Skins/}" | cut -d/ -f1
done
done | sort -u
)
if [ "${#deleted_skins[@]}" -gt 0 ]; then
for d in "${deleted_skins[@]}"; do
@@ -217,9 +219,8 @@ jobs:
shell: bash
run: |
echo "Creating base directories for assets..."
mkdir -p "$REPO_SCREENSHOT_DIR" "$REPO_MOD_ICONS_DIR" "$REPO_RANKING_PANEL_DIR" "$OSK_PATH"
mkdir -p "$REPO_SCREENSHOT_DIR" "$REPO_MOD_ICONS_DIR" "$REPO_RANKING_PANEL_DIR" "$OSK_PATH" "$REPO_THUMBNAIL_DIR"
# Read the newline-delimited list back into an array
readarray -t skins <<< "$ALL_SKINS_DIR"
for skin in "${skins[@]}"; do
@@ -228,7 +229,8 @@ jobs:
"$REPO_SCREENSHOT_DIR/$skin" \
"$REPO_MOD_ICONS_DIR/$skin" \
"$REPO_RANKING_PANEL_DIR/$skin" \
"$OSK_PATH/$skin"
"$OSK_PATH/$skin" \
"$REPO_THUMBNAIL_DIR/$skin"
done
echo "All asset directories created for ${#skins[@]} skins."
@@ -279,50 +281,73 @@ jobs:
[ ! -d "$SKIN_DIR" ] && { echo "Skipping missing skin: $skin_path"; continue; }
SKIN_NAME="$skin_path"
OUT_GIF_DIR="$REPO_SCREENSHOT_DIR/$SKIN_NAME"
OUT_VIDEO_DIR="$REPO_SCREENSHOT_DIR/$SKIN_NAME"
OUT_PNG_DIR="$REPO_RANKING_PANEL_DIR/$SKIN_NAME"
OUT_THUMBNAIL_DIR="$REPO_THUMBNAIL_DIR/$SKIN_NAME"
echo ""
echo "[$INDEX/$SKIN_COUNT] Generating for skin: $SKIN_NAME"
LOGFILE="/tmp/danser_log_$INDEX.txt"
FFMPEG_LOG="/tmp/ffmpeg_log_$INDEX.txt"
echo " → Generating video..."
if ! xvfb-run -a "$DANSER_DIR/danser-cli" \
-replay "$REPLAY_PATH" -record -skip -start=215 -end=230 -noupdatecheck \
-replay "$GAMEPLAY_REPLAY_PATH" -record -skip -start=300 -end=307 -noupdatecheck \
-out="$SKIN_NAME" -skin="$SKIN_NAME" >"$LOGFILE" 2>&1; then
echo " ✖ Video failed for $SKIN_NAME"; cat "$LOGFILE"; INDEX=$((INDEX+1)); continue
fi
echo " → Taking screenshot..."
if ! xvfb-run -a "$DANSER_DIR/danser-cli" \
-replay "$REPLAY_PATH" -skip -noupdatecheck -ss 243 \
-out="$SKIN_NAME" -skin="$SKIN_NAME" >>"$LOGFILE" 2>&1; then
echo " ✖ Screenshot failed for $SKIN_NAME"; cat "$LOGFILE"; INDEX=$((INDEX+1)); continue
fi
if [ -f "$DANSER_VIDEO_DIR/$SKIN_NAME.mp4" ]; then
echo " → Converting to GIF..."
if ffmpeg -y -hwaccel cuda -ss 4 -t 10 -i "$DANSER_VIDEO_DIR/$SKIN_NAME.mp4" \
-filter_complex "[0:v] fps=24,scale=720:-1:flags=lanczos,palettegen [p]; [0:v] fps=24,scale=720:-1:flags=lanczos [x]; [x][p] paletteuse" \
-c:v gif "$DANSER_VIDEO_DIR/$SKIN_NAME.gif" >"$FFMPEG_LOG" 2>&1; then
mv "$DANSER_VIDEO_DIR/$SKIN_NAME.gif" "$OUT_GIF_DIR/$SKIN_NAME.gif"
echo " ✓ GIF moved to $OUT_GIF_DIR/"
echo " → Trimming MP4 with ffmpeg..."
ffmpeg -hide_banner -loglevel error \
-ss 5 -t 6.5 \
-i "$DANSER_VIDEO_DIR/$SKIN_NAME.mp4" \
-c:v h264_nvenc -preset fast \
-c:a aac -b:a 128k \
"$DANSER_VIDEO_DIR/${SKIN_NAME}_trimmed.mp4"
if [ -f "$DANSER_VIDEO_DIR/${SKIN_NAME}_trimmed.mp4" ]; then
mv "$DANSER_VIDEO_DIR/${SKIN_NAME}_trimmed.mp4" "$DANSER_VIDEO_DIR/$SKIN_NAME.mp4"
mkdir -p "$OUT_VIDEO_DIR"
mv "$DANSER_VIDEO_DIR/$SKIN_NAME.mp4" "$OUT_VIDEO_DIR/$SKIN_NAME.mp4"
echo " ✓ Trimmed MP4 moved to $OUT_VIDEO_DIR/"
else
echo " ✖ FFmpeg conversion failed for $SKIN_NAME"; cat "$FFMPEG_LOG"
echo " ✖ ffmpeg trimming failed for $SKIN_NAME"
fi
else
echo " ✖ No MP4 found for $SKIN_NAME"
fi
echo " → Taking screenshot..."
if ! xvfb-run -a "$DANSER_DIR/danser-cli" \
-replay "$PANEL_REPLAY_PATH" -skip -noupdatecheck -ss 28 \
-out="$SKIN_NAME" -skin="$SKIN_NAME" >>"$LOGFILE" 2>&1; then
echo " ✖ Screenshot failed for $SKIN_NAME"; cat "$LOGFILE"; INDEX=$((INDEX+1)); continue
fi
if [ -f "$DANSER_SCREENSHOT_DIR/$SKIN_NAME.png" ]; then
mkdir -p "$OUT_PNG_DIR"
mv "$DANSER_SCREENSHOT_DIR/$SKIN_NAME.png" "$OUT_PNG_DIR/$SKIN_NAME.png"
echo " ✓ PNG moved to $OUT_PNG_DIR/"
else
echo " ✖ No PNG found for $SKIN_NAME"
fi
echo " → Taking thumbnail screenshot..."
if ! xvfb-run -a "$DANSER_DIR/danser-cli" \
-replay "$THUMBNAIL_REPLAY_PATH" -skip -noupdatecheck -ss 1.3 \
-out="${SKIN_NAME}_thumb" -skin="$SKIN_NAME" >>"$LOGFILE" 2>&1; then
echo " ✖ Thumbnail screenshot failed for $SKIN_NAME"; cat "$LOGFILE"; INDEX=$((INDEX+1)); continue
fi
if [ -f "$DANSER_SCREENSHOT_DIR/${SKIN_NAME}_thumb.png" ]; then
mkdir -p "$OUT_THUMBNAIL_DIR"
mv "$DANSER_SCREENSHOT_DIR/${SKIN_NAME}_thumb.png" "$OUT_THUMBNAIL_DIR/$SKIN_NAME.png"
echo " ✓ Thumbnail PNG moved to $OUT_THUMBNAIL_DIR/"
else
echo " ✖ No thumbnail PNG found for $SKIN_NAME"
fi
INDEX=$((INDEX + 1))
done
@@ -370,18 +395,21 @@ jobs:
if [ -n "$name_line" ]; then
val="${name_line#*:}"
val="$(echo "$val" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
if [ -n "$val" ]; then
sanitized="$(sanitize_filename "$val")"
[ -n "$sanitized" ] && skin_header="$sanitized"
fi
fi
fi
GIF_DIR="$REPO_SCREENSHOT_DIR/$SKIN_DIR_NAME"
VIDEO_DIR="$REPO_SCREENSHOT_DIR/$SKIN_DIR_NAME"
PNG_DIR="$REPO_RANKING_PANEL_DIR/$SKIN_DIR_NAME"
THUMBNAIL_DIR="$REPO_THUMBNAIL_DIR/$SKIN_DIR_NAME"
if [ -f "$GIF_DIR/$SKIN_DIR_NAME.gif" ] && [ "$SKIN_DIR_NAME" != "$skin_header" ]; then
mv -f "$GIF_DIR/$SKIN_DIR_NAME.gif" \
"$GIF_DIR/$skin_header.gif" || true
echo " ✓ Renamed GIF to $GIF_DIR/$skin_header.gif"
if [ -f "$VIDEO_DIR/$SKIN_DIR_NAME.mp4" ] && [ "$SKIN_DIR_NAME" != "$skin_header" ]; then
mv -f "$VIDEO_DIR/$SKIN_DIR_NAME.mp4" \
"$VIDEO_DIR/$skin_header.mp4" || true
echo " ✓ Renamed MP4 to $VIDEO_DIR/$skin_header.mp4"
fi
if [ -f "$PNG_DIR/$SKIN_DIR_NAME.png" ] && [ "$SKIN_DIR_NAME" != "$skin_header" ]; then
@@ -390,13 +418,19 @@ jobs:
echo " ✓ Renamed PNG to $PNG_DIR/$skin_header.png"
fi
if [ -f "$THUMBNAIL_DIR/$SKIN_DIR_NAME.png" ] && [ "$SKIN_DIR_NAME" != "$skin_header" ]; then
mv -f "$THUMBNAIL_DIR/$SKIN_DIR_NAME.png" \
"$THUMBNAIL_DIR/$skin_header.png" || true
echo " ✓ Renamed thumbnail to $THUMBNAIL_DIR/$skin_header.png"
fi
INDEX=$((INDEX + 1))
done
echo ""
echo "[Asset Renaming Complete — processed $SKIN_COUNT skins]"
- name: Generate Mod Icons
- name: Generate Mod Icons (WEBP)
shell: bash
run: |
echo "[Mod Icon Generation Job Started]"
@@ -438,10 +472,12 @@ jobs:
if [ -n "$name_line" ]; then
val="${name_line#*:}"
val="$(echo "$val" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
if [ -n "$val" ]; then
sanitized="$(sanitize_filename "$val")"
[ -n "$sanitized" ] && skin_header="$sanitized"
fi
fi
fi
echo ""
echo "[$INDEX/$SKIN_COUNT] Skin: $skin_header"
@@ -449,7 +485,7 @@ jobs:
ICON_FOLDER="$SKIN_DIR"
OUTPUT_DIR="$REPO_MOD_ICONS_DIR/$skin_path"
mkdir -p "$OUTPUT_DIR"
OUTPUT="$OUTPUT_DIR/${skin_header}-mod-icons.png"
OUTPUT="$OUTPUT_DIR/${skin_header}-mod-icons.webp"
row_images=()
row_index=1
@@ -457,15 +493,22 @@ jobs:
for group_list in "$group1_icons" "$group2_icons" "$group3_icons"; do
montage_files=()
for icon in $group_list; do
file=""
if [ -f "${ICON_FOLDER}/selection-mod-${icon}@2x.png" ]; then
montage_files+=("${ICON_FOLDER}/selection-mod-${icon}@2x.png")
file="${ICON_FOLDER}/selection-mod-${icon}@2x.png"
elif [ -f "${ICON_FOLDER}/selection-mod-${icon}.png" ]; then
file="${ICON_FOLDER}/selection-mod-${icon}.png"
elif [ -f "${DEFAULT_SKIN_DIR}/selection-mod-${icon}@2x.png" ]; then
montage_files+=("${DEFAULT_SKIN_DIR}/selection-mod-${icon}@2x.png")
file="${DEFAULT_SKIN_DIR}/selection-mod-${icon}@2x.png"
fi
[ -n "$file" ] && montage_files+=("$file")
done
while [ "${#montage_files[@]}" -lt 7 ]; do
montage_files+=("$BLANK_IMAGE")
done
magick montage "${montage_files[@]}" \
-tile "7x1" -geometry "160x160+10+10" -background none \
"row_${row_index}.png"
@@ -475,8 +518,10 @@ jobs:
magick montage "${row_images[@]}" \
-tile "1x${#row_images[@]}" -geometry "+10+10" -background none \
"$OUTPUT"
rm row_*.png
"temp_combined.png"
magick "temp_combined.png" -define webp:lossless=true "$OUTPUT"
rm temp_combined.png row_*.png
echo " ✓ Mod Icons Generated at $OUTPUT"
INDEX=$((INDEX + 1))
@@ -487,6 +532,40 @@ jobs:
echo ""
echo "[Mod Icon Generation Finished — processed $SKIN_COUNT skins]"
- name: Convert PNGs to WEBPs
shell: bash
run: |
echo "[Convert PNG → WEBP Started]"
if [ -z "${CHANGED_SKINS_FILE:-}" ] || [ ! -s "$CHANGED_SKINS_FILE" ]; then
echo "No skins changed. Skipping conversion."
exit 0
fi
mapfile -t skins < "$CHANGED_SKINS_FILE"
[ "${#skins[@]}" -eq 0 ] && { echo "No skins to process. Exiting."; exit 0; }
convert_pngs_to_webp() {
local base_dir="$1"
local skin_path="$2"
local dir="$base_dir/$skin_path"
echo " → Processing: $dir"
[ ! -d "$dir" ] && { echo " ✖ Directory does not exist: $dir"; return; }
find "$dir" -type f -iname "*.png" | while read -r png; do
webp="${png%.png}.webp"
echo " ↳ Converting: $png → $webp"
magick "$png" -define webp:lossless=false -quality 90 "$webp" && rm -f "$png"
done
}
for skin_path in "${skins[@]}"; do
[ -z "$skin_path" ] && continue
convert_pngs_to_webp "$REPO_RANKING_PANEL_DIR" "$skin_path"
convert_pngs_to_webp "$REPO_THUMBNAIL_DIR" "$skin_path"
done
echo "[Convert PNG → WEBP Finished]"
- name: Create OSK Files
shell: bash
run: |
@@ -525,10 +604,12 @@ jobs:
if [ -n "$name_line" ]; then
val="${name_line#*:}"
val="$(echo "$val" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
if [ -n "$val" ]; then
sanitized="$(sanitize_filename "$val")"
[ -n "$sanitized" ] && skin_header="$sanitized"
fi
fi
fi
echo ""
echo "[$INDEX/$SKIN_COUNT] Processing skin: $skin_header"
@@ -549,27 +630,28 @@ jobs:
- name: Generate README
shell: bash
run: |
echo "Starting README generation..."
echo "Generating README index…"
sanitize_filename() {
echo "$1" | \
tr -d '\000-\037' | \
sed -e 's#[\\/:\*\?"<>|]#-#g' | \
sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
sed -e 's#[\\/:\*\?"<>|]#-#g' -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
}
url_encode_path() {
local raw_path="$1"
echo "$raw_path" | tr -d '\r\n' | jq -sRr @uri
local IFS='/'
local parts=($1)
local encoded=""
for part in "${parts[@]}"; do
[ -n "$encoded" ] && encoded+="/"
encoded+=$(printf '%s' "$part" | jq -sRr @uri)
done
echo "$encoded"
}
SKINS_JSON_FILE="${{ github.workspace }}/.gitea/workflows/skins.json"
DESC_FILE=$(mktemp)
echo "Step 1: Extracting descriptions from skins.json..."
jq -r '.descriptions | to_entries[] | "\(.key)=\(.value)"' "$SKINS_JSON_FILE" > "$DESC_FILE"
echo "Step 2: Starting to build README..."
echo "---" > "$README_PATH"
echo "gitea: none" >> "$README_PATH"
echo "include_toc: true" >> "$README_PATH"
@@ -583,33 +665,42 @@ jobs:
echo "" >> "$README_PATH"
echo "**Go back to [osc/skins]($REGISTRY_URL/osc/skins)**" >> "$README_PATH"
echo "" >> "$README_PATH"
echo "**Click on the Skin name to download it, or click on the thumbnail to see more about the skin, including a video preview, screenshots, and mod icons.**" >> "$README_PATH"
echo "" >> "$README_PATH"
jq -r '.descriptions | to_entries[] | "\(.key)=\(.value)"' "$SKINS_JSON_FILE" > "$DESC_FILE"
jq -r '.order[]?' "$SKINS_JSON_FILE" > order.txt
get_desc() {
grep -F -m1 -- "$1=" "$DESC_FILE" 2>/dev/null | cut -d '=' -f2-
grep -F -m1 -- "$1=" "$DESC_FILE" 2>/dev/null | cut -d '=' -f2- || true
}
ORDER_FILE=$(mktemp)
echo "Step 3: Extracting order from skins.json..."
jq -r '.order[]?' "$SKINS_JSON_FILE" > "$ORDER_FILE"
echo "Step 4: Processing ordered skins..."
declare -A ordered
while IFS= read -r skin; do
echo " Processing skin (order): $skin"
[ "$skin" = "default-skin" ] && continue
ordered["$skin"]=1
dir="$DANSER_SKINS_DIR/$skin"
[ ! -d "$dir" ] && { echo " Skipping missing directory: $dir"; continue; }
[ ! -d "$dir" ] && continue
ini_file=$(find "$dir" -maxdepth 1 -iname "skin.ini" | head -n1)
ini_file=$(find "$dir" -maxdepth 1 -iname "skin.ini" | head -n1 || true)
skin_header="$skin"
if [ -f "$ini_file" ]; then
line=$(grep -i '^[[:space:]]*Name:' "$ini_file" | head -n1 2>/dev/null || true)
[ -n "$line" ] && {
val="${line#*:}"
skin_header=$(sanitize_filename "$val")
}
name_line=$(grep -a -i -m1 'Name[[:space:]]*:' "$ini_file" || true)
if [ -n "$name_line" ]; then
val="${name_line#*:}"
val="$(echo "$val" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
[ -n "$val" ] && skin_header=$(sanitize_filename "$val")
else
skin_header=$(sanitize_filename "$skin")
fi
else
continue
fi
raw_path="$(printf "%s/%s" "$skin" "$skin_header" | sed 's/^ *//;s/ *$//')"
base_path=$(url_encode_path "$raw_path")
echo "## [$skin_header]($REGISTRY_URL/$USER_REPOSITORY/media/tag/$new_tag/export/${base_path}.osk)" >> "$README_PATH"
echo "" >> "$README_PATH"
@@ -617,71 +708,57 @@ jobs:
[ -n "$desc" ] && { echo "$desc" >> "$README_PATH"; echo "" >> "$README_PATH"; }
if [ -f "$ini_file" ]; then
author_line=$(grep -i '^[[:space:]]*Author:' "$ini_file" | head -n1 2>/dev/null || true)
author_line=$(grep -i '^[[:space:]]*Author:' "$ini_file" | head -n1 || true)
if [ -n "$author_line" ]; then
author="${author_line#*:}"
author="$(sanitize_filename "$author")"
author=$(echo "$author_line" | cut -d ':' -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$author" ] && { echo "**Author:** $author" >> "$README_PATH"; echo "" >> "$README_PATH"; }
fi
fi
echo "![$skin_header Gameplay](media/gameplay/${base_path}.gif)" >> "$README_PATH"
echo "[![$skin_header Thumbnail](media/thumbnail/${base_path}.webp)](/docs/${base_path}.md)" >> "$README_PATH"
echo "" >> "$README_PATH"
echo "![$skin_header Ranking Panel](media/panel/${base_path}.png)" >> "$README_PATH"
echo "" >> "$README_PATH"
echo "![$skin_header Mods](media/icons/${base_path}-mod-icons.png)" >> "$README_PATH"
echo "" >> "$README_PATH"
done < "$ORDER_FILE"
done < order.txt
declare -A ordered
while IFS= read -r skin; do
ordered["$skin"]=1
done < "$ORDER_FILE"
echo "Step 5: Processing extra skins..."
if [ ! -s "$ORDER_FILE" ]; then
echo "→ No \`order\` defined in skins.json; skipping extra-skins loop."
else
for dir in "$DANSER_SKINS_DIR"/*; do
[ -d "$dir" ] || continue
skin=$(basename "$dir")
skin="$(basename "$dir")"
[ "$skin" = "default-skin" ] && continue
[[ -n "${ordered[$skin]}" ]] && continue
echo " Writing extra skin: $skin"
ini_file=$(find "$dir" -maxdepth 1 -iname "skin.ini" | head -n1)
ini_file=$(find "$dir" -maxdepth 1 -iname "skin.ini" | head -n1 || true)
skin_header="$skin"
if [ -f "$ini_file" ]; then
line=$(grep -i '^[[:space:]]*Name:' "$ini_file" | head -n1 2>/dev/null || true)
[ -n "$line" ] && {
val="${line#*:}"
skin_header=$(sanitize_filename "$val")
}
name_line=$(grep -a -i -m1 'Name[[:space:]]*:' "$ini_file" || true)
if [ -n "$name_line" ]; then
val="${name_line#*:}"
val="$(echo "$val" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
[ -n "$val" ] && skin_header=$(sanitize_filename "$val")
else
skin_header=$(sanitize_filename "$skin")
fi
else
continue
fi
raw_path="$(printf "%s/%s" "$skin" "$skin_header" | sed 's/^ *//;s/ *$//')"
base_path=$(url_encode_path "$raw_path")
echo "## [$skin_header]($REGISTRY_URL/$USER_REPOSITORY/media/tag/$new_tag/export/${base_path}.osk)" >> "$README_PATH"
echo "" >> "$README_PATH"
if [ -f "$ini_file" ]; then
author_line=$(grep -i '^[[:space:]]*Author:' "$ini_file" | head -n1 2>/dev/null || true)
author_line=$(grep -i '^[[:space:]]*Author:' "$ini_file" | head -n1 || true)
if [ -n "$author_line" ]; then
author="${author_line#*:}"
author="$(sanitize_filename "$author")"
author=$(echo "$author_line" | cut -d ':' -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -n "$author" ] && { echo "**Author:** $author" >> "$README_PATH"; echo "" >> "$README_PATH"; }
fi
fi
echo "![$skin_header Gameplay](media/gameplay/${base_path}.gif)" >> "$README_PATH"
echo "" >> "$README_PATH"
echo "![$skin_header Ranking Panel](media/panel/${base_path}.png)" >> "$README_PATH"
echo "" >> "$README_PATH"
echo "![$skin_header Mods](media/icons/${base_path}-mod-icons.png)" >> "$README_PATH"
echo "[![$skin_header Thumbnail](media/thumbnail/${base_path}.webp)](/docs/${base_path}.md)" >> "$README_PATH"
echo "" >> "$README_PATH"
done
fi
echo "Step 7: Writing Build History section..."
echo "# Build History" >> "$README_PATH"
echo "" >> "$README_PATH"
echo "| Version | Date |" >> "$README_PATH"
@@ -699,7 +776,114 @@ jobs:
done
fi
echo "README generation completed successfully."
echo "README index generated successfully."
- name: Generate Per-Skin Pages
shell: bash
run: |
echo "Generating detailed per-skin markdown pages…"
sanitize_filename() {
echo "$1" | \
tr -d '\000-\037' | \
sed -e 's#[\\/:\*\?"<>|]#-#g' | \
sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
}
url_encode_path() {
local IFS='/'
local parts=($1)
local encoded=""
for part in "${parts[@]}"; do
[ -n "$encoded" ] && encoded+="/"
encoded+=$(printf '%s' "$part" | jq -sRr @uri)
done
echo "$encoded"
}
mkdir -p "$DOC_DIR"
for dir in "$DANSER_SKINS_DIR"/*; do
[ -d "$dir" ] || continue
skin=$(basename "$dir")
[ "$skin" = "default-skin" ] && continue
ini_file=$(find "$dir" -maxdepth 1 -iname "skin.ini" | head -n1 || true)
skin_header="$skin"
if [ -f "$ini_file" ]; then
line=$(grep -i '^[[:space:]]*Name:' "$ini_file" | head -n1 || true)
if [ -n "$line" ]; then
val="${line#*:}"
val="$(echo "$val" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
if [ -n "$val" ]; then
skin_header=$(sanitize_filename "$val")
fi
fi
fi
raw_path="${skin}/${skin_header}"
base_path=$(url_encode_path "$raw_path")
osk_url="$REGISTRY_URL/$USER_REPOSITORY/media/tag/$new_tag/export/${base_path}.osk"
md_file_path="${DOC_DIR}/${raw_path}.md"
mkdir -p "$(dirname "$md_file_path")"
video_url="$REGISTRY_URL/$USER_REPOSITORY/media/tag/$new_tag/media/gameplay/${base_path}.mp4"
author=""
if [ -f "$ini_file" ]; then
author_line=$(grep -i '^[[:space:]]*Author:' "$ini_file" | head -n1 || true)
if [ -n "$author_line" ]; then
author=$(echo "$author_line" | cut -d ':' -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
fi
fi
{
echo "# [$skin_header]($osk_url)"
echo ""
[ -n "$author" ] && echo "**Author:** $author"
[ -n "$author" ] && echo ""
echo "## Hitsounds"
echo "<video controls autoplay loop muted playsinline src=\"$video_url\" type=\"video/mp4\">"
echo "</video>"
echo ""
echo "## Ranking Panel"
echo "![](/media/panel/${base_path}.webp)"
echo ""
echo "## Mod Icons"
echo "![](/media/icons/${base_path}-mod-icons.webp)"
echo ""
echo "## Build History"
echo ""
echo "| Version | Date |"
echo "| ------- | ---- |"
current_commit_date=$(TZ="Europe/Zurich" date -d "$(git log -1 --format=%cI)" "+%d.%m.%Y %H:%M:%S")
echo "| [\`$new_tag (Current)\`]($REGISTRY_URL/$USER_REPOSITORY/src/tag/$new_tag/docs/${base_path}.md) | $current_commit_date |"
old_tags=$(git tag --sort=-v:refname | grep -v "^$new_tag$" | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' || true)
if [ -n "$old_tags" ]; then
echo "$old_tags" | while read -r tag; do
raw_osk_path="export/${skin}/${skin_header}.osk"
if git ls-tree -r --name-only "$tag" | grep -Fx -- "$raw_osk_path" >/dev/null; then
tag_date=$(git log -1 --format=%ci "$tag")
formatted_date=$(TZ="Europe/Zurich" date -d "$tag_date" "+%d.%m.%Y %H:%M:%S")
echo "| [\`$tag\`]($REGISTRY_URL/$USER_REPOSITORY/src/tag/$tag/docs/${base_path}.md) | $formatted_date |"
fi
done
fi
} > "$md_file_path"
echo " → Wrote $md_file_path"
done
echo "Per-skin markdown pages complete."
- name: Cleanup Extra Files
shell: bash
@@ -707,8 +891,9 @@ jobs:
set -euo pipefail
echo "[Cleanup Extra Files Started]"
[ -d src/docs ] && rm -rf src/docs
[ -f how-to-use.md ] && rm -f how-to-use.md
[ -f src/replay.osr ] && rm -f src/replay.osr
[ -d src/default-skin ] && rm -rf src/default-skin
readarray -t skins <<< "$ALL_SKINS_DIR"
@@ -719,7 +904,34 @@ jobs:
sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
}
for root in "$REPO_SCREENSHOT_DIR" "$REPO_RANKING_PANEL_DIR" "$REPO_MOD_ICONS_DIR" "$OSK_PATH"; do
prune_dir() {
local root="$1"
local skin="$2"
local expected="$3"
for f in "$root"/*; do
[ -f "$f" ] || continue
name="$(basename "$f")"
if printf '%s\n' "${skins[@]}" | grep -Fxq -- "$name"; then
continue
fi
echo " → Removing unexpected root file: $f"
rm -f "$f"
done
dir="$root/$skin"
[ -d "$dir" ] || return
for f in "$dir"/*; do
[ -e "$f" ] || continue
if [[ "$(basename "$f")" != "$expected" ]]; then
echo " → Removing unexpected file: $f"
rm -f "$f"
fi
done
}
for root in "$REPO_SCREENSHOT_DIR" "$REPO_RANKING_PANEL_DIR" "$REPO_MOD_ICONS_DIR" "$REPO_THUMBNAIL_DIR" "$OSK_PATH" "$DOC_DIR"; do
[ -d "$root" ] || continue
for dir in "$root"/*; do
[ -d "$dir" ] || continue
name="$(basename "$dir")"
@@ -736,34 +948,17 @@ jobs:
if [[ -f "$ini" ]]; then
raw=$(grep -i '^[[:space:]]*Name:' "$ini" | head -n1 || true)
raw="${raw#*:}"
raw="$(echo "$raw" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
tmp_header=$(sanitize_filename "$raw")
if [[ -n "$tmp_header" ]]; then
header="$tmp_header"
fi
[[ -n "$tmp_header" ]] && header="$tmp_header"
fi
expect_gif="$header.gif"
expect_png="$header.png"
expect_icon="$header-mod-icons.png"
expect_osk="$header.osk"
prune_dir() {
root=$1; expected=$2
dir="$root/$skin"
[ ! -d "$dir" ] && return
for f in "$dir"/*; do
[ -e "$f" ] || continue
if [[ "$(basename "$f")" != "$expected" ]]; then
echo " → Removing unexpected file: $f"
rm -f "$f"
fi
done
}
prune_dir "$REPO_SCREENSHOT_DIR" "$expect_gif"
prune_dir "$REPO_RANKING_PANEL_DIR" "$expect_png"
prune_dir "$REPO_MOD_ICONS_DIR" "$expect_icon"
prune_dir "$OSK_PATH" "$expect_osk"
prune_dir "$REPO_SCREENSHOT_DIR" "$skin" "$header.mp4"
prune_dir "$REPO_RANKING_PANEL_DIR" "$skin" "$header.webp"
prune_dir "$REPO_MOD_ICONS_DIR" "$skin" "$header-mod-icons.webp"
prune_dir "$REPO_THUMBNAIL_DIR" "$skin" "$header.webp"
prune_dir "$OSK_PATH" "$skin" "$header.osk"
prune_dir "$DOC_DIR" "$skin" "$header.md"
done
echo "[Cleanup Extra Files Complete]"
@@ -779,7 +974,7 @@ jobs:
run: |
git config advice.addIgnoredFile false
for p in media/gameplay media/panel media/icons export README.md how-to-use.md src; do
for p in docs/ media/gameplay media/thumbnail media/panel media/icons export README.md how-to-use.md src; do
if [ -e "$p" ]; then
git add -A "$p"
fi

View File

@@ -1,10 +1,10 @@
{
"order": [
"example1",
"example2"
"Rafis 2018-03-26 HDDT",
"aristiatekkito"
],
"descriptions": {
"example1": "Description of example1",
"example2": "Description of example2"
"Rafis 2018-03-26 HDDT": "My main DT skin (aristiatekkito cursor)",
"aristiatekkito": "My main everything other than DT skin"
}
}

3
.gitignore vendored
View File

@@ -0,0 +1,3 @@
*boop*
*fiery*
*Umbre*

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,207 @@
[General]
Name: Aristia(Edit (Mistya))
Author: [Garin] + Aristia + Various
Version: 2.4
SliderBallFlip: 1
CursorRotate: 0
CursorTrailRotate: 0
CursorExpand: 0
CursorCentre: 1
SliderBallFrames: 60
HitCircleOverlayAboveNumer: 1
SliderStyle: 2
AllowSliderBallTint: 1
SpinnerFadePlayfield: 0
[Colours]
Combo1: 26,116,242
Combo2: 164,32,240
Combo3: 37,185,239
Combo4: 23,209,116
Combo5: 255,75,255
//Combo1: 255,75,255
//Combo2: 37,185,239
//Combo3: 26,116,242
SongSelectActiveText: 250,250,250
SongSelectInactiveText: 230,230,230
SliderBorder: 120,120,120
SliderTrackOverride: 3,3,12
[Fonts]
HitCirclePrefix: default
HitCircleOverlap: 6
//The prefix for the score font sprites (top left of interface)
ScorePrefix: num\berlin
ScoreOverlap: 0
//The prefix for the combo font sprites (bottom left of interface)
ComboPrefix: num\berlin
ComboOverlap: 5
[Mania]
Keys: 4
//Mania skin config
ColumnStart: 340
HitPosition: 400
SpecialStyle: 0
UpsideDown: 0
JudgementLine: 0
ScorePosition: 300
ComboPosition: 275
LightFramePerSecond: 24
ColumnWidth: 45,45,45,45
ColumnLineWidth: 0,0,0,0,0
BarlineHeight: 0
//Colours
ColourLight1: 102,205,107,175
ColourLight2: 69,188,250,175
ColourLight3: 69,188,250,175
ColourLight4: 102,205,107,175
Colour1: 0,0,0,240
Colour2: 0,0,0,240
Colour3: 0,0,0,240
Colour4: 0,0,0,240
ColourHold: 255,230,0,255
[Mania]
Keys: 5
//Mania skin config
ColumnStart: 336
HitPosition: 400
SpecialStyle: 0
UpsideDown: 0
JudgementLine: 0
ScorePosition: 300
ComboPosition: 275
LightFramePerSecond: 24
ColumnWidth: 43,40,44,40,43
ColumnLineWidth: 0,0,0,0,0,0
BarlineHeight: 0
//Colours
ColourLight1: 102,205,107,175
ColourLight2: 69,188,250,175
ColourLight3: 205,102,102,175
ColourLight4: 69,188,250,175
ColourLight5: 102,205,107,175
Colour1: 0,0,0,240
Colour2: 0,0,0,240
Colour3: 0,0,0,240
Colour4: 0,0,0,240
Colour5: 0,0,0,240
ColourHold: 255,230,0,255
//images
KeyImage2: mania-keyS
KeyImage2D: mania-keySD
NoteImage2: mania-noteS
NoteImage2H: mania-noteSH
NoteImage2L: mania-noteSL
[Mania]
Keys: 6
//Mania skin config
ColumnStart: 336
HitPosition: 400
SpecialStyle: 0
UpsideDown: 0
JudgementLine: 0
ScorePosition: 300
ComboPosition: 275
LightFramePerSecond: 24
ColumnWidth: 38,35,38,35,38,35
ColumnLineWidth: 0,0,0,0,0,0,0
BarlineHeight: 0
//Colours
ColourLight1: 102,205,107,175
ColourLight2: 69,188,250,175
ColourLight3: 102,205,107,175
ColourLight4: 102,205,107,175
ColourLight5: 69,188,250,175
ColourLight6: 102,205,107,175
Colour1: 0,0,0,240
Colour2: 0,0,0,240
Colour3: 0,0,0,240
Colour4: 0,0,0,240
Colour5: 0,0,0,240
Colour6: 0,0,0,240
ColourHold: 255,230,0,255
[Mania]
Keys: 7
//Mania skin config
ColumnStart: 336
HitPosition: 400
ScorePosition: 300
ComboPosition: 275
JudgementLine: 0
LightFramePerSecond: 24
ColumnWidth: 36,34,36,38,36,34,38
ColumnLineWidth: 0,0,0,0,0,0,0,0
BarlineHeight: 0
//Colours
ColourLight1: 102,205,170,255
ColourLight2: 69,188,250,175
ColourLight3: 102,205,170,255
ColourLight4: 205,102,102,175
ColourLight5: 102,205,170,255
ColourLight6: 69,188,250,175
ColourLight7: 102,205,170,255
Colour1: 0,0,0,240
Colour2: 0,0,0,240
Colour3: 0,0,0,240
Colour4: 0,0,0,240
Colour5: 0,0,0,240
Colour6: 0,0,0,240
Colour7: 0,0,0,240
ColourHold: 255,230,0,255
[Mania]
Keys: 8
//Mania skin config
ColumnStart: 336
Barline: 0
HitPosition: 400
SpecialStyle: 1
UpsideDown: 0
JudgementLine: 0
ScorePosition: 300
ComboPosition: 275
LightFramePerSecond: 24
ColumnWidth: 45,28,25,28,25,28,25,28
ColumnLineWidth: 0,2,2,2,2,2,2,2,0
BarlineHeight: 0
//Colours
Colour1: 0,0,0,240
Colour2: 24,24,24,240
Colour3: 0,0,0,240
Colour4: 24,24,24,240
Colour5: 0,0,0,240
Colour6: 24,24,24,240
Colour7: 0,0,0,240
Colour8: 24,24,24,240
ColourLight1: 205,102,102,175
ColourLight2: 102,205,107,175
ColourLight3: 69,188,250,175
ColourLight4: 102,205,107,175
ColourLight5: 69,188,250,175
ColourLight6: 102,205,107,175
ColourLight7: 69,188,250,175
ColourLight8: 102,205,107,175
ColourHold: 255,255,255,255
ColourColumnLine: 99,99,99,255
ColourHold: 255,230,0,255
//images
KeyImage0: Mania-keyT
KeyImage0D: Mania-KeyTD

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More