shader audit: ignore .xcf, allow _suffix for effect textures
[xonotic/xonotic-maps.pk3dir.git] / scripts / shader-audit.sh
1 #!/bin/sh
2
3 LF="
4 "
5
6 normalize()
7 {
8         echo "$1" | sed 's/\.\(tga\|jpg\|png\)$//'
9 }
10
11 allowed_prefixes=
12 forbidden_prefixes=
13
14 textures_used=
15 # $1 = shader
16 # $2 = texture
17 # $3 = shader | map | animmap | editorimage | sky
18 use_texture()
19 {
20         # does texture exist?
21         if \
22                 [ -f "../$2.tga" ] || \
23                 [ -f "../$2.jpg" ] || \
24                 [ -f "../$2.png" ]; then
25                 :
26         else
27                 if [ "$3" = "shader" ]; then
28                         return
29                 else
30                         echo "(EE) shader $1 uses non-existing texture $2"
31                 fi
32         fi
33         textures_used="$textures_used$LF$2"
34
35         if [ -n "$allowed_prefixes" ]; then
36                 ok=false
37                 for p in $allowed_prefixes; do
38                         case "$1:" in
39                                 "$p"*)
40                                         ok=true
41                                         ;;
42                         esac
43                 done
44         else
45                 ok=true
46         fi
47         for p in $forbidden_prefixes; do
48                 case "$1:" in
49                         "$p"*)
50                                 ok=false
51                                 ;;
52                 esac
53         done
54         if ! $ok; then
55                 echo "(EE) shader $1 is not allowed in this shader file (allowed: $allowed_prefixes, forbidden: $forbidden_prefixes)"
56         fi
57
58         case "$3" in
59                 sky)
60                         case "$2" in
61                                 env/*)
62                                         ;;
63                                 *)
64                                         echo "(EE) texture $2 of shader $1 is out of place, $3 textures must be in env/"
65                                         ;;
66                         esac
67                         ;;
68                 *)
69                         case "$2" in
70                                 env/*)
71                                         echo "(EE) texture $2 of shader $1 is out of place, $3 textures must not be in env/"
72                                         ;;
73                                 *)
74                                         ;;
75                         esac
76                         ;;
77         esac
78
79         # verify shader -> texture name
80         case "$1" in
81                 textures/*x/*-*)
82                         pre=${1%%x/*}x
83                         suf=${1#*x/}
84                         # rule: in suffix part, change each - to /
85                         suf="`echo "$suf" | sed 's,-,/,g'`"
86                         case "$2" in
87                                 "$pre"/*/*)
88                                         ;;
89                                 *)
90                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $pre/$suf"
91                                         ;;
92                         esac
93                         ;;
94                 textures/*x/*)
95                         pre=${1%%x/*}x
96                         suf=${1#*x/}
97                         case "$2" in
98                                 "$pre"/*/*)
99                                         ;;
100                                 *)
101                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $pre/base/$suf"
102                                         ;;
103                         esac
104                         ;;
105                 textures/map_*/*)
106                         pre=${1%%/map_*}
107                         suf=${1#*/map_}
108                         map=${suf%%[_/]*}
109                         case "$2" in
110                                 "$pre"/map_$map[/_]*)
111                                         ;;
112                                 *)
113                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $pre/map_$map/*"
114                                         ;;
115                         esac
116                         ;;
117                 textures/common/*)
118                         case "$2" in
119                                 "$1")
120                                         ;;
121                                 textures/common/*/*)
122                                         ;;
123                                 *)
124                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $1 or textures/common/*/*"
125                                         ;;
126                         esac
127                         ;;
128                 textures/decals/*|textures/liquids/water/*|textures/liquids/slime/*|textures/liquids/lava/*|textures/warpzone/*)
129                         prefix=${1%%_*}
130                         case "$2" in
131                                 "$prefix"_*|"$prefix")
132                                         # I _suppose_ this is fine, as tZork committed this pack
133                                         ;;
134                                 *)
135                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $1"
136                                         ;;
137                         esac
138                         ;;
139                 textures/skies/*)
140                         sky=${1#textures/skies/}
141                         sky=${sky%%_*}
142                         case "$2" in
143                                 "$1")
144                                         # typical place for preview image
145                                         ;;
146                                 env/$sky[/_]*)
147                                         # typical place for skybox
148                                         ;;
149                                 *)
150                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $1"
151                                         ;;
152                         esac
153                         ;;
154                 models/*)
155                         case "$2" in
156                                 models/*)
157                                         ;;
158                                 *)
159                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $1 or models/*"
160                                         ;;
161                         esac
162                         ;;
163                 *)
164                         echo "(EE) no shader name pattern for $1"
165                         ;;
166         esac
167 }
168
169 parsing_shader=
170 parse_shaderstage()
171 {
172         while read L A1 A2 Aother; do
173                 case "$L" in
174                         map)
175                                 case "$A1" in
176                                         '$lightmap')
177                                                 ;;
178                                         *)
179                                                 use_texture "$parsing_shader" "`normalize "$A1"`" map
180                                                 ;;
181                                 esac
182                                 ;;
183                         animmap)
184                                 for X in $A2 $Aother; do
185                                         use_texture "$parsing_shader" "`normalize "$X"`" animmap
186                                 done
187                                 ;;
188                         '}')
189                                 break
190                                 ;;
191                         *)
192                                 ;;
193                 esac
194         done
195 }
196
197 parse_shader()
198 {
199         use_texture "$parsing_shader" "$parsing_shader" shader
200         while read L A1; do
201                 case "$L" in
202                         qer_editorimage\ *)
203                                 use_texture "$parsing_shader" "$A1" editorimage
204                                 ;;
205                         skyparms\ *)
206                                 use_texture "$parsing_shader" "$A1" sky
207                                 ;;
208                         '{')
209                                 parse_shaderstage
210                                 ;;
211                         '}')
212                                 break
213                                 ;;
214                         *)
215                                 ;;
216                 esac
217         done
218 }
219
220 parse_shaderfile()
221 {
222         case "$1" in
223                 map_*)
224                         allowed_prefixes="textures/map_`echo "$1" | cut -d _ -f 2`_ textures/map_`echo "$1" | cut -d - -f 2`/"
225                         forbidden_prefixes=
226                         ;;
227                 skies_*)
228                         allowed_prefixes="textures/skies/`echo "$1" | cut -d _ -f 2`: textures/skies/`echo "$1" | cut -d _ -f 2`_"
229                         forbidden_prefixes=
230                         ;;
231                 *)
232                         allowed_prefixes=
233                         forbidden_prefixes="textures/skies/ textures/map_"
234                         ;;
235         esac
236         while read L; do
237                 case "$L" in
238                         */*)
239                                 parsing_shader="`normalize "$L"`"
240                                 if [ x"$L" != x"$parsing_shader" ]; then
241                                         echo "(WW) normalized shader name $L to $parsing_shader"
242                                 fi
243                                 ;;
244                         '{')
245                                 parse_shader
246                                 ;;
247                         *)
248                                 ;;
249                 esac
250         done
251 }
252
253 strip_comments()
254 {
255         sed 's,//.*,,g; s,\r, ,g; s,\t, ,g; s,  *, ,g; s, $,,; s,^ ,,; /^$/ d'
256 }
257
258 t=`mktemp`
259 for X in *.shader; do
260         strip_comments < "$X" > "$t"
261         parse_shaderfile "${X%.shader}" < "$t"
262 done
263 rm -f "$t"
264
265 textures_avail=`( cd ..; find textures/ -type f -not -name '*_norm.*' -not -name '*_glow.*' -not -name '*_gloss.*' -not -name '*.xcf' ) | while IFS= read -r T; do normalize "$T"; done | sort -u`
266 textures_used=`echo "${textures_used#$LF}" | sort -u`
267
268 echo "$textures_used$LF$textures_used$LF$textures_avail" | sort | uniq -u | while IFS= read -r L; do
269         case "$L" in
270                 textures/radiant/*)
271                         ;;
272                 textures/map_*/*)
273                         ;;
274                 *)
275                         echo "(EE) texture $L is not referenced by any shader"
276                         ;;
277         esac
278 done