allow models/*
[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 = self | map | animmap | editorimage
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" = "self" ]; 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         # TODO verify shader -> texture name
59         case "$1" in
60                 textures/*x/*-*)
61                         pre=${1%%x/*}x
62                         suf=${1#*x/}
63                         # rule: in suffix part, change each - to /
64                         suf="`echo "$suf" | sed 's,-,/,g'`"
65                         case "$2" in
66                                 "$pre"/*/*)
67                                         ;;
68                                 *)
69                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $pre/$suf"
70                                         ;;
71                         esac
72                         ;;
73                 textures/*x/*)
74                         pre=${1%%x/*}x
75                         suf=${1#*x/}
76                         case "$2" in
77                                 "$pre"/*/*)
78                                         ;;
79                                 *)
80                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $pre/base/$suf"
81                                         ;;
82                         esac
83                         ;;
84                 textures/map_*/*)
85                         pre=${1%%/map_*}
86                         suf=${1#*/map_}
87                         map=${suf%%[_/]*}
88                         case "$2" in
89                                 "$pre"/map_$map[/_]*)
90                                         ;;
91                                 *)
92                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $pre/map_$map/*"
93                                         ;;
94                         esac
95                         ;;
96                 textures/common/*)
97                         case "$2" in
98                                 "$1")
99                                         ;;
100                                 textures/common/*/*)
101                                         ;;
102                                 *)
103                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $1 or textures/common/*/*"
104                                         ;;
105                         esac
106                         ;;
107                 textures/decals/*)
108                         case "$2" in
109                                 "$1")
110                                         # I _suppose_ this is fine, as tZork committed this pack
111                                         ;;
112                                 *)
113                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $1"
114                                         ;;
115                         esac
116                         ;;
117                 textures/skies/*)
118                         sky=${1#textures/skies/}
119                         case "$2" in
120                                 "$1")
121                                         # typical place for preview image
122                                         ;;
123                                 env/"${1#textures/skies/}")
124                                         # typical place for skybox
125                                         ;;
126                                 *)
127                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $1"
128                                         ;;
129                         esac
130                         ;;
131                 models/*)
132                         case "$2" in
133                                 models/*)
134                                         ;;
135                                 *)
136                                         echo "(EE) texture $2 of shader $1 is out of place, recommended file name is $1 or models/*"
137                                         ;;
138                         esac
139                         ;;
140                 *)
141                         echo "(EE) no shader name pattern for $1"
142                         ;;
143         esac
144 }
145
146 parsing_shader=
147 parse_shaderstage()
148 {
149         while read L A1 A2 Aother; do
150                 case "$L" in
151                         map)
152                                 case "$A1" in
153                                         '$lightmap')
154                                                 ;;
155                                         *)
156                                                 use_texture "$parsing_shader" "`normalize "$A1"`" map
157                                                 ;;
158                                 esac
159                                 ;;
160                         animmap)
161                                 for X in $A2 $Aother; do
162                                         use_texture "$parsing_shader" "`normalize "$X"`" animmap
163                                 done
164                                 ;;
165                         '}')
166                                 break
167                                 ;;
168                         *)
169                                 ;;
170                 esac
171         done
172 }
173
174 parse_shader()
175 {
176         use_texture "$parsing_shader" "$parsing_shader" self
177         while read L A1; do
178                 case "$L" in
179                         qer_editorimage\ *)
180                                 use_texture "$parsing_shader" "$A1" editorimage
181                                 ;;
182                         '{')
183                                 parse_shaderstage
184                                 ;;
185                         '}')
186                                 break
187                                 ;;
188                         *)
189                                 ;;
190                 esac
191         done
192 }
193
194 parse_shaderfile()
195 {
196         case "$1" in
197                 map_*)
198                         allowed_prefixes="textures/map_`echo "$1" | cut -d _ -f 2`_ textures/map_`echo "$1" | cut -d - -f 2`/"
199                         forbidden_prefixes=
200                         ;;
201                 skies_*)
202                         allowed_prefixes="textures/skies/`echo "$1" | cut -d _ -f 2`: textures/skies/`echo "$1" | cut -d _ -f 2`_"
203                         forbidden_prefixes=
204                         ;;
205                 *)
206                         allowed_prefixes=
207                         forbidden_prefixes="textures/skies/ textures/map_"
208                         ;;
209         esac
210         while read L; do
211                 case "$L" in
212                         */*)
213                                 parsing_shader="`normalize "$L"`"
214                                 if [ x"$L" != x"$parsing_shader" ]; then
215                                         echo "(WW) normalized shader name $L to $parsing_shader"
216                                 fi
217                                 ;;
218                         '{')
219                                 parse_shader
220                                 ;;
221                         *)
222                                 ;;
223                 esac
224         done
225 }
226
227 strip_comments()
228 {
229         sed 's,//.*,,g; s,\r, ,g; s,\t, ,g; s,  *, ,g; s, $,,; s,^ ,,; /^$/ d'
230 }
231
232 t=`mktemp`
233 for X in *.shader; do
234         strip_comments < "$X" > "$t"
235         parse_shaderfile "${X%.shader}" < "$t"
236 done
237 rm -f "$t"
238
239 textures_avail=`( cd ..; find textures/ -type f -not -name '*_norm.*' -not -name '*_glow.*' -not -name '*_gloss.*' ) | while IFS= read -r T; do normalize "$T"; done | sort -u`
240 textures_used=`echo "${textures_used#$LF}" | sort -u`
241
242 echo "$textures_used$LF$textures_used$LF$textures_avail" | sort | uniq -u | while IFS= read -r L; do
243         case "$L" in
244                 textures/radiant/*)
245                         ;;
246                 textures/map_*/*)
247                         ;;
248                 *)
249                         echo "(EE) texture $L is not referenced by any shader"
250                         ;;
251         esac
252 done