1#! /bin/bash 2 3# Functions 4function init_vars { 5 if [ "${LDRAW_CAT_HI_RES}" != "" ]; then 6 export CATALOG_DIR=${HOME}/tmp/LDrawCatalog-high 7 else 8 export CATALOG_DIR=${HOME}/tmp/LDrawCatalog 9 fi 10 export LAST_DIR=${CATALOG_DIR}/last 11 export IMG_DIR=${CATALOG_DIR}/img 12 export FULL_DIR=${CATALOG_DIR}/full 13 export CAT_DIR=${CATALOG_DIR}/cat 14 export CSS_FILENAME=LDrawPartsCatalog.css 15 export MAIN_FILENAME=LDrawPartsCatalog.html 16 export FULL_FILENAME=LDrawOfflinePartsCatalog.html 17 export CATALOG=${CATALOG_DIR}/${MAIN_FILENAME} 18 export FULL_CATALOG=${FULL_DIR}/${FULL_FILENAME} 19 export CATEGORY_BASE=${CAT_DIR}/LDraw 20 export ALL_PARTS_LIST=${CATALOG_DIR}/AllLDrawParts.txt 21 export LAST_ALL_PARTS_LIST=${LAST_DIR}/AllLDrawParts.txt 22 export PARTS_LIST=${CATALOG_DIR}/LDrawParts.txt 23 export LAST_PARTS_LIST=${LAST_DIR}/LDrawParts.txt 24 export BASEPLATES_LIST=${CATALOG_DIR}/LDrawBaseplates.txt 25 export LAST_BASEPLATES_LIST=${LAST_DIR}/LDrawBaseplates.txt 26 export PANELS_LIST=${CATALOG_DIR}/LDrawPanels.txt 27 export LAST_PANELS_LIST=${LAST_DIR}/LDrawPanels.txt 28 export CATEGORIES_LIST=${CATALOG_DIR}/Categories.txt 29 export LDRAW_DIR=${HOME}/Library/ldraw 30 export LDVIEW=/Applications/LDView.app/Contents/MacOS/LDView 31} 32 33function print_part_row { 34 png_filename=${part_filename%.dat}.png 35 png_size=`file "${IMG_DIR}/${png_filename}" | cut -d , -f 2` 36 png_width=`echo ${png_size} | cut -d ' ' -f 1` 37 png_height=`echo ${png_size} | cut -d ' ' -f 3` 38 if [ "${LDRAW_CAT_HI_RES}" != "" ]; then 39 (( png_width /= 2 )) 40 (( png_height /= 2 )) 41 fi 42 if [ "${keywords}" != "" ]; then 43 rowspan=3 44 else 45 rowspan=2 46 fi 47 echo ' <tr valign="top"> 48 <td rowspan='${rowspan}' align="right"><img width="'${png_width}'" height="'${png_height}'" src="../img/'${png_filename}'" alt="Part Image"/></td> 49 <td class="label" align="right" height="99%"><font size="-2">File</font></td><td>'${part_filename}'</td> 50 </tr> 51 <tr valign="top"><td class="label" align="right"><font size="-2">Name</font></td><td>'${desc}'</td></tr>' 52 if [ "${keywords}" != "" ]; then 53 echo ' <tr valign="top"><td class="label" align="right"><font size="-2">Keywords</font></td><td>'${keywords}'</td></tr>' 54 fi 55} 56 57function get_part_desc { 58 if [ -e "${1}" ]; then 59 part_desc=`head -n 1 ${1} | sed 's/ 60$//' | sed -E 's/^0[ ]+//' | tr -d '\n'` 61 if [[ "${part_desc}" =~ ^~Moved\ to\ ]]; then 62 old_part_desc=${part_desc} 63 new_part=`echo "${part_desc}" | sed -E 's/~Moved to //'` 64 get_part_desc "${new_part}.dat" 65 fi 66 fi 67} 68 69function process_part { 70 get_vars_from_line ${*} 71 export CATEGORY_FILE=${CATEGORY_BASE}${cat}.html 72 print_part_row >> "${CATEGORY_FILE}" 73 print_part_row >> "${FULL_CATALOG}" 74} 75 76function pre_process_part { 77 get_vars_from_line ${*} 78 get_part_desc ${part_filename} 79 if [[ "${part_desc}" =~ [Bb][Aa][Ss][Ee][Pp][Ll][Aa][Tt][Ee] ]]; then 80 if [ "${cmdline}" == "" ]; then 81 echo ${part_filename} >> ${BASEPLATES_LIST} 82 else 83 echo ${part_filename}${cmdline} >> ${BASEPLATES_LIST}-cmdline 84 fi 85 elif [[ "${part_filename}" =~ ^(4864|6268|4215|2362|4865|4345ap|4345bp)[^0-9] ]]; then 86 if [ "${cmdline}" == "" ]; then 87 echo ${part_filename} >> ${PANELS_LIST} 88 else 89 echo ${part_filename}${cmdline} >> ${PANELS_LIST}-cmdline 90 fi 91 else 92 if [ "${cmdline}" == "" ]; then 93 echo ${part_filename} >> ${PARTS_LIST} 94 else 95 echo ${part_filename}${cmdline} >> ${PARTS_LIST}-cmdline 96 fi 97 fi 98} 99 100function find_meta_value { 101 meta_value=`grep -E '^[ ]*0[ ]+\'$2'[ ]+' $1 | sed -E -e 's/^[ ]*0[ ]+\'$2'[ ]+//' -e 's/ 102//g'` 103} 104 105function find_category { 106 find_meta_value $1 "!CATEGORY" 107 if [ "${meta_value}" == "" ]; then 108 part_cat=`echo ${orig_part_desc} | cut -f 1 -d ' ' | sed -E 's/^[_~=]+//'` 109 else 110 part_cat=$meta_value 111 fi 112} 113 114function find_cmdline { 115# find_meta_value $1 "!CMDLINE" 116# if [ "${meta_value}" != "" ]; then 117# part_cmdline=${meta_value} 118# else 119# unset part_cmdline 120# fi 121 unset part_cmdline 122} 123 124function find_keywords { 125 meta_value=`grep -E '^[ ]*0[ ]+\!KEYWORDS[ ]+' $1 | sed -E -e 's/^[ ]*0[ ]+\!KEYWORDS[ ]+//' -e 's/ 126//g' -e 's/$/, /'` 127 if [ "${meta_value}" != "" ]; then 128 part_keywords=`echo ${meta_value} | sed 's/,$//'` 129 else 130 unset part_keywords 131 fi 132} 133 134function print_part_scan { 135 orig_part_desc=`head -n 1 ${1} | sed 's/ 136$//' | sed -E 's/^0[ ]+//' | tr -d '\n'` 137 find_category $1 138 find_cmdline $1 139 find_keywords $1 140 echo -e ${part_cat}${orig_part_desc}${1}${part_cmdline}${part_keywords} 141} 142 143function scan_part { 144 print_part_scan $1 >> ${ALL_PARTS_LIST} 145} 146 147function print_style_sheet { 148echo 'body 149{ 150 font-family: tahoma, sans-serif; 151} 152 153p 154{ 155 margin-top: 0px; 156 margin-bottom: 0px; 157} 158 159div 160{ 161 position: absolute; 162} 163 164table 165{ 166 border-collapse: collapse; 167 border: 2px solid #000000; 168 background-color: #FFFFFF; 169 padding: 0px; 170} 171 172tr 173{ 174 page-break-inside: avoid; 175} 176 177th 178{ 179 background-color: #0080D0; 180 color: #FFFFFF; 181 border-bottom: 1px solid #000000; 182 border-right: 1px solid #00558A; 183 padding: 4px 8px; 184} 185 186th.title 187{ 188 background-color: #EEEEEE; 189 color: #000000; 190 font-size: 150%; 191} 192 193td 194{ 195 background-color: #FFFFFF; 196 border-bottom: 1px solid #BFBFBF; 197 border-right: 1px solid #BFBFBF; 198 padding: 2px 4px; 199} 200 201td.label 202{ 203 text-align: right; 204 border-right: 0px; 205 width: 1%; 206 padding: 2px 0px 2px 4px; 207} 208 209table.credits 210{ 211 border-collapse: collapse; 212 border-style: none; 213 background-color: transparent; 214 margin: 0px; 215 width: 100%; 216} 217 218td.credits 219{ 220 background-color: #EEEEEE; 221 border-style: none; 222 padding: 0px; 223} 224 225table.credits td 226{ 227 background-color: transparent; 228 color: #808080; 229 border-style: none; 230 font-size: 65%; 231} 232 233a 234{ 235 text-decoration: none; 236 border-style: none; 237} 238 239a:link 240{ 241 color: #000080; 242} 243 244a:visited 245{ 246 color: #0000FF; 247} 248 249a:hover 250{ 251 text-decoration: underline; 252 color: #000080; 253} 254 255img 256{ 257 float: right; 258} 259 260a img 261{ 262 border-style: none; 263} 264 265:link:hover img 266{ 267 background-color: #D0E8FF; 268} 269 270:visited:hover img 271{ 272 background-color: #A0C0FF; 273}' 274} 275 276function create_style_sheet { 277 print_style_sheet > "${CATALOG_DIR}/${CSS_FILENAME}" 278} 279 280function print_header { 281echo '<!DOCTYPE html> 282<html> 283<head> 284<title>'${1}'</title>' 285echo '<style type="text/css" title="Standard"><!--' 286print_style_sheet 287echo '--></style>' 288#echo '<link href="'${2}${CSS_FILENAME}'" title="Standard" rel="stylesheet" type="text/css">' 289echo '</head> 290<body>' 291} 292 293function print_cat_header { 294 print_header "${*}" ../ 295 #echo '<p><a href="../'${MAIN_FILENAME}'">Back</a></p>' 296 echo '<table> 297 <thead> 298 <tr> 299 <th colspan="3">'${*}'</th> 300 </tr> 301 </thead> 302 <tbody>' 303} 304 305function print_full_header { 306 print_header "${*}" ../ 307 echo '<table> 308 <tbody>' 309} 310 311function print_main_header { 312 print_header "${*}" 313echo '<table> 314 <thead> 315 <tr> 316 <th>Category</th> 317 </tr> 318 </thead> 319 <tbody>' 320} 321 322function create_main_header { 323 rm -f ${CATALOG} 324 print_main_header LDraw Parts > "${CATALOG}" 325} 326 327function create_full_header { 328 rm -f ${CATALOG} 329 print_full_header LDraw Parts > "${FULL_CATALOG}" 330} 331 332function create_cat_header { 333 export CATEGORY_FILE=${CATEGORY_BASE}${1}.html 334 rm -f ${CATEGORY_FILE} 335 print_cat_header ${1} > "${CATEGORY_FILE}" 336} 337 338function print_footer { 339echo ' </tbody> 340</table> 341</body> 342</html>' 343} 344 345function create_cat_footer { 346 export CATEGORY_FILE=${CATEGORY_BASE}${1}.html 347 print_footer >> "${CATEGORY_FILE}" 348} 349 350function create_full_footer { 351 print_footer >> "${FULL_CATALOG}" 352} 353 354function create_main_footer { 355 print_footer >> "${CATALOG}" 356} 357 358function create_images { 359 image_size=512 360 edge_thickness=1 361 if [ "${LDRAW_CAT_HI_RES}" != "" ]; then 362 image_size=1024 363 edge_thickness=2 364 fi 365 while [ `stat -f %z ${1}` -gt 0 ] 366 do 367 ldview_command_line="${LDVIEW} -LDrawDir=${LDRAW_DIR} ${2} -FOV=0.1 -SaveSnapshots=1 -SaveDir=${IMG_DIR} -SaveWidth=${image_size} -SaveHeight=${image_size} -EdgeThickness=${edge_thickness} -SaveZoomToFit=1 -AutoCrop=1 -SaveAlpha=1 -LineSmoothing=1 -BFC=0 -PreferenceSet=LDPartsCatalog `head -n 50 ${1}`" 368 $ldview_command_line 369 if [ $? != 0 ]; then 370 # LDView occasionally just stops in the middle. Since that is going 371 # to be a really hard bug to track down, retry the LDView command 372 # if it fails the first time. 373 echo LDView failed. Trying one more time. 374 $ldview_command_line 375 fi 376 tail -n +51 ${1} > ${1}.tmp 377 mv ${1}.tmp ${1} 378 done 379 rm -f "${1}" 380 while read line 381 do 382 get_cmdline_vars_from_line ${line} 383 if [[ "${cmdline}" =~ ^-[cC](.*) ]]; then 384 default_color=-DefaultColorNumber=${BASH_REMATCH[1]} 385 else 386 unset default_color 387 fi 388 ldview_command_line="${LDVIEW} -LDrawDir=${LDRAW_DIR} ${2} -FOV=0.1 -SaveSnapshots=1 -SaveDir=${IMG_DIR} -SaveWidth=${image_size} -SaveHeight=${image_size} -EdgeThickness=${edge_thickness} -SaveZoomToFit=1 -AutoCrop=1 -SaveAlpha=1 -LineSmoothing=1 -BFC=0 ${default_color} ${part_filename}" 389 $ldview_command_line 390 done < "${1}-cmdline" 391 rm -f "${1}-cmdline" 392} 393 394function create_empty_list { 395 rm -f ${1} 396 touch ${1} 397} 398 399function create_empty_lists { 400 create_empty_list ${ALL_PARTS_LIST} 401 create_empty_list ${PARTS_LIST} 402 create_empty_list ${PARTS_LIST}-cmdline 403 create_empty_list ${BASEPLATES_LIST} 404 create_empty_list ${BASEPLATES_LIST}-cmdline 405 create_empty_list ${PANELS_LIST} 406 create_empty_list ${PANELS_LIST}-cmdline 407} 408 409function process_parts { 410 while read line 411 do 412 process_part ${line} 413 done < "${ALL_PARTS_LIST}" 414} 415 416function pre_process_parts { 417 if [ -e ${LAST_PARTS_LIST} ] && [ -e ${LAST_PARTS_LIST}-cmdline ] && [ -e ${LAST_BASEPLATES_LIST} ] && [ -e ${LAST_BASEPLATES_LIST}-cmdline ] && [ -e ${LAST_PANELS_LIST} ] && [ -e ${LAST_PANELS_LIST}-cmdline ]; then 418 cp ${LAST_PARTS_LIST} ${PARTS_LIST} 419 cp ${LAST_PARTS_LIST}-cmdline ${PARTS_LIST}-cmdline 420 cp ${LAST_BASEPLATES_LIST} ${BASEPLATES_LIST} 421 cp ${LAST_BASEPLATES_LIST}-cmdline ${BASEPLATES_LIST}-cmdline 422 cp ${LAST_PANELS_LIST} ${PANELS_LIST} 423 cp ${LAST_PANELS_LIST}-cmdline ${PANELS_LIST}-cmdline 424 return 425 fi 426 echo Preprocessing part information... 427 while read line 428 do 429 pre_process_part ${line} 430 done < "${ALL_PARTS_LIST}" 431 cp ${PARTS_LIST} ${LAST_DIR}/ 432 cp ${PARTS_LIST}-cmdline ${LAST_DIR}/ 433 cp ${BASEPLATES_LIST} ${LAST_DIR}/ 434 cp ${BASEPLATES_LIST}-cmdline ${LAST_DIR}/ 435 cp ${PANELS_LIST} ${LAST_DIR}/ 436 cp ${PANELS_LIST}-cmdline ${LAST_DIR}/ 437} 438 439function process_command_line { 440 if [ "${1}" == "-hi" ]; then 441 echo Generating high-resolution images. 442 LDRAW_CAT_HI_RES=1 443 else 444 unset LDRAW_CAT_HI_RES 445 fi 446} 447 448function verify_dir { 449 if [ ! -d "${1}" ]; then 450 mkdir -p "${1}" 451 fi 452 if [ ! -d "${1}" ]; then 453 echo Error creating directory ${1}. 454 exit 455 fi 456} 457 458function verify_settings { 459 verify_dir "${LAST_DIR}" 460 verify_dir "${CATALOG_DIR}" 461 verify_dir "${IMG_DIR}" 462 verify_dir "${CAT_DIR}" 463 verify_dir "${FULL_DIR}" 464 if [ ! -d ${LDRAW_DIR} ]; then 465 echo LDraw directory not found at ${LDRAW_DIR} 466 exit 467 fi 468} 469 470function scan_parts { 471 cd ${LDRAW_DIR}/parts 472 if [ -e ${LAST_ALL_PARTS_LIST} ]; then 473 cp ${LAST_ALL_PARTS_LIST} ${ALL_PARTS_LIST} 474 else 475 echo Scanning parts... 476 for partFile in *.dat 477 do 478 scan_part ${partFile} 479 done 480 echo Sorting parts list... 481 # Set locale to UTF-8 for sorting, since LDraw officially uses UTF-8 482 export LC_ALL=UTF-8 483 sort -f ${ALL_PARTS_LIST} > ${ALL_PARTS_LIST}.tmp 484 mv ${ALL_PARTS_LIST}.tmp ${ALL_PARTS_LIST} 485 cp ${ALL_PARTS_LIST} ${LAST_ALL_PARTS_LIST} 486 fi 487 cut -d -f 1 ${ALL_PARTS_LIST} | sort -u > ${CATEGORIES_LIST} 488} 489 490function generate_part_images { 491 num_imgs=`ls ${IMG_DIR}/ | wc -l` 492 num_parts=`cat ${ALL_PARTS_LIST} | wc -l` 493 if [ ${num_imgs} != ${num_parts} ]; then 494 echo Generating panel part images... 495 create_images ${PANELS_LIST} -cg30,225,275000 496 echo Generating baseplate part images... 497 create_images ${BASEPLATES_LIST} -cg30,45,550000 498 echo Generating standard part images... 499 create_images ${PARTS_LIST} -cg30,45,275000 500 else 501 echo Images already generated. 502 fi 503} 504 505function print_cat_row { 506 echo ' <tr> 507 <td><a href="cat/LDraw'${1/ /%20}'.html">'${*}'</a></td> 508 </tr>' 509} 510 511function create_cat_row { 512 print_cat_row "${*}" >> "${CATALOG}" 513} 514 515function generate_html { 516 echo Generating HTML... 517 create_style_sheet 518 create_full_header 519 create_main_header 520 while read line 521 do 522 create_cat_header "${line}" 523 create_cat_row "${line}" 524 done < "${CATEGORIES_LIST}" 525 create_main_footer 526 process_parts 527 create_full_footer 528 while read line 529 do 530 create_cat_footer ${line} 531 done < "${CATEGORIES_LIST}" 532 echo HTML created. 533} 534 535function get_cmdline_vars_from_line { 536 if [[ "${*}" =~ ([^]*)([^]*) ]]; then 537 part_filename=${BASH_REMATCH[1]} 538 cmdline=${BASH_REMATCH[2]} 539 fi 540} 541 542function get_vars_from_line { 543 if [[ "${*}" =~ ([^]*)([^]*)([^]*)([^]*)([^]*) ]]; then 544 cat=${BASH_REMATCH[1]} 545 desc=${BASH_REMATCH[2]} 546 part_filename=${BASH_REMATCH[3]} 547 cmdline=${BASH_REMATCH[4]} 548 keywords=${BASH_REMATCH[5]} 549 fi 550} 551 552# Main program 553process_command_line ${*} 554init_vars 555verify_settings 556create_empty_lists 557scan_parts 558pre_process_parts 559generate_part_images 560generate_html 561rm -f ${ALL_PARTS_LIST} 562