1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * @constant 29 * @type Number 30 */ 31 cc.SAX_NONE = 0; 32 33 /** 34 * @constant 35 * @type Number 36 */ 37 cc.SAX_KEY = 1; 38 39 /** 40 * @constant 41 * @type Number 42 */ 43 cc.SAX_DICT = 2; 44 45 /** 46 * @constant 47 * @type Number 48 */ 49 cc.SAX_INT = 3; 50 51 /** 52 * @constant 53 * @type Number 54 */ 55 cc.SAX_REAL = 4; 56 57 /** 58 * @constant 59 * @type Number 60 */ 61 cc.SAX_STRING = 5; 62 63 /** 64 * @constant 65 * @type Number 66 */ 67 cc.SAX_ARRAY = 6; 68 69 //Compatibility with IE9 70 var Uint8Array = Uint8Array || Array; 71 72 if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { 73 var IEBinaryToArray_ByteStr_Script = 74 "<!-- IEBinaryToArray_ByteStr -->\r\n" + 75 //"<script type='text/vbscript'>\r\n" + 76 "Function IEBinaryToArray_ByteStr(Binary)\r\n" + 77 " IEBinaryToArray_ByteStr = CStr(Binary)\r\n" + 78 "End Function\r\n" + 79 "Function IEBinaryToArray_ByteStr_Last(Binary)\r\n" + 80 " Dim lastIndex\r\n" + 81 " lastIndex = LenB(Binary)\r\n" + 82 " if lastIndex mod 2 Then\r\n" + 83 " IEBinaryToArray_ByteStr_Last = Chr( AscB( MidB( Binary, lastIndex, 1 ) ) )\r\n" + 84 " Else\r\n" + 85 " IEBinaryToArray_ByteStr_Last = " + '""' + "\r\n" + 86 " End If\r\n" + 87 "End Function\r\n";// + 88 //"</script>\r\n"; 89 90 // inject VBScript 91 //document.write(IEBinaryToArray_ByteStr_Script); 92 var myVBScript = document.createElement('script'); 93 myVBScript.type = "text/vbscript"; 94 myVBScript.textContent = IEBinaryToArray_ByteStr_Script; 95 document.body.appendChild(myVBScript); 96 97 // helper to convert from responseBody to a "responseText" like thing 98 cc._convertResponseBodyToText = function (binary) { 99 var byteMapping = {}; 100 for (var i = 0; i < 256; i++) { 101 for (var j = 0; j < 256; j++) { 102 byteMapping[ String.fromCharCode(i + j * 256) ] = 103 String.fromCharCode(i) + String.fromCharCode(j); 104 } 105 } 106 var rawBytes = IEBinaryToArray_ByteStr(binary); 107 var lastChr = IEBinaryToArray_ByteStr_Last(binary); 108 return rawBytes.replace(/[\s\S]/g, 109 function (match) { 110 return byteMapping[match]; 111 }) + lastChr; 112 }; 113 } 114 115 /** 116 * @namespace 117 */ 118 cc.FileUtils = cc.Class.extend({ 119 _fileDataCache:null, 120 _textFileCache:null, 121 122 _directory:null, 123 _filenameLookupDict:null, 124 _searchResolutionsOrderArray:null, 125 _searchPathArray:null, 126 _defaultResRootPath:"", 127 128 ctor:function () { 129 this._fileDataCache = {}; 130 this._textFileCache = {}; 131 132 this._searchPathArray = []; 133 this._searchPathArray.push(this._defaultResRootPath); 134 135 this._searchResolutionsOrderArray = []; 136 this._searchResolutionsOrderArray.push(""); 137 }, 138 139 /** 140 * <p> 141 * Purges the file searching cache. <br/> 142 * <br/> 143 * @note It should be invoked after the resources were updated. <br/> 144 * For instance, in the CocosPlayer sample, every time you run application from CocosBuilder, <br/> 145 * All the resources will be downloaded to the writable folder, before new js app launchs, <br/> 146 * this method should be invoked to clean the file search cache. 147 * </p> 148 */ 149 purgeCachedEntries:function(){ 150 this._searchPathArray = []; 151 }, 152 /** 153 * Get Byte Array from file 154 * @function 155 * @param {String} fileName The resource file name which contain the path 156 * @param {String} mode mode The read mode of the file 157 * @param {Number} size If get the file data succeed the it will be the data size,or it will be 0 158 * @warning If you get the file data succeed,you must delete it after used. 159 */ 160 getByteArrayFromFile:function (fileName, mode, size) { 161 fileName = this.fullPathForFilename(fileName); 162 if (this._fileDataCache.hasOwnProperty(fileName)) 163 return this._fileDataCache[fileName]; 164 return this._loadBinaryFileData(fileName); 165 }, 166 167 _getXMLHttpRequest:function () { 168 if (window.XMLHttpRequest) { 169 return new window.XMLHttpRequest(); 170 } else { 171 return new ActiveXObject("MSXML2.XMLHTTP"); 172 } 173 }, 174 175 unloadBinaryFileData:function (fileUrl) { 176 if (this._fileDataCache.hasOwnProperty(fileUrl)) 177 delete this._fileDataCache[fileUrl]; 178 }, 179 180 preloadBinaryFileData:function (fileUrl) { 181 fileUrl = this.fullPathForFilename(fileUrl); 182 var selfPointer = this; 183 184 var xhr = this._getXMLHttpRequest(); 185 xhr.open("GET", fileUrl, true); 186 if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { 187 // IE-specific logic here 188 xhr.setRequestHeader("Accept-Charset", "x-user-defined"); 189 xhr.onreadystatechange = function (event) { 190 if (xhr.readyState == 4) { 191 if (xhr.status == 200) { 192 var fileContents = cc._convertResponseBodyToText(xhr["responseBody"]); 193 if (fileContents) 194 selfPointer._fileDataCache[fileUrl] = selfPointer._stringConvertToArray(fileContents); 195 } else { 196 cc.Loader.getInstance().onResLoadingErr(fileUrl); 197 } 198 cc.Loader.getInstance().onResLoaded(); 199 } 200 }; 201 } else { 202 if (xhr.overrideMimeType) 203 xhr.overrideMimeType("text\/plain; charset=x-user-defined"); 204 205 xhr.onreadystatechange = function (event) { 206 if (xhr.readyState == 4) { 207 if (xhr.status == 200) { 208 var fileContents = xhr.responseText; 209 if (fileContents) 210 selfPointer._fileDataCache[fileUrl] = selfPointer._stringConvertToArray(fileContents); 211 } else { 212 cc.Loader.getInstance().onResLoadingErr(fileUrl); 213 } 214 cc.Loader.getInstance().onResLoaded(); 215 } 216 }; 217 } 218 xhr.send(null); 219 }, 220 221 _loadBinaryFileData:function (fileUrl) { 222 var req = this._getXMLHttpRequest(); 223 req.open('GET', fileUrl, false); 224 var arrayInfo = null; 225 if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { 226 req.setRequestHeader("Accept-Charset", "x-user-defined"); 227 req.send(null); 228 if (req.status != 200) 229 return null; 230 231 var fileContents = cc._convertResponseBodyToText(req["responseBody"]); 232 if (fileContents) { 233 arrayInfo = this._stringConvertToArray(fileContents); 234 this._fileDataCache[fileUrl] = arrayInfo; 235 } 236 } else { 237 if (req.overrideMimeType) 238 req.overrideMimeType('text\/plain; charset=x-user-defined'); 239 req.send(null); 240 if (req.status != 200) 241 return null; 242 243 arrayInfo = this._stringConvertToArray(req.responseText); 244 this._fileDataCache[fileUrl] = arrayInfo; 245 } 246 return arrayInfo; 247 }, 248 249 _stringConvertToArray:function (strData) { 250 if (!strData) 251 return null; 252 253 var arrData = new Uint8Array(strData.length); 254 for (var i = 0; i < strData.length; i++) { 255 arrData[i] = strData.charCodeAt(i) & 0xff; 256 } 257 return arrData; 258 }, 259 260 unloadTextFileData:function (fileUrl) { 261 if (this._textFileCache.hasOwnProperty(fileUrl)) 262 delete this._textFileCache[fileUrl]; 263 }, 264 265 preloadTextFileData:function (fileUrl) { 266 fileUrl = this.fullPathForFilename(fileUrl); 267 var selfPointer = this; 268 269 var xhr = this._getXMLHttpRequest(); 270 xhr.open("GET", fileUrl, true); 271 if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { 272 // IE-specific logic here 273 xhr.setRequestHeader("Accept-Charset", "utf-8"); 274 } else { 275 if (xhr.overrideMimeType) 276 xhr.overrideMimeType("text\/plain; charset=utf-8"); 277 } 278 xhr.onreadystatechange = function (event) { 279 if (xhr.readyState == 4) { 280 if (xhr.status == 200) { 281 var fileContents = xhr.responseText; 282 if (fileContents) 283 selfPointer._textFileCache[fileUrl] = fileContents; 284 } else { 285 cc.Loader.getInstance().onResLoadingErr(fileUrl); 286 } 287 cc.Loader.getInstance().onResLoaded(); 288 } 289 }; 290 xhr.send(null); 291 }, 292 293 _loadTextFileData:function (fileUrl) { 294 var req = this._getXMLHttpRequest(); 295 req.open('GET', fileUrl, false); 296 var fileContents = null; 297 if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { 298 req.setRequestHeader("Accept-Charset", "utf-8"); 299 } else { 300 if (req.overrideMimeType) 301 req.overrideMimeType('text\/plain; charset=utf-8'); 302 } 303 req.send(null); 304 if (req.status != 200) 305 return null; 306 307 fileContents = req.responseText; 308 if (fileContents) { 309 this._textFileCache[fileUrl] = fileContents; 310 } 311 return fileContents; 312 }, 313 314 /** 315 * Gets resource file data 316 * @param {String} fileUrl The resource file name which contains the path. 317 * @returns {String} 318 */ 319 getTextFileData:function (fileUrl) { 320 if (this._textFileCache.hasOwnProperty(fileUrl)) 321 return this._textFileCache[fileUrl]; 322 return this._loadTextFileData(fileUrl); 323 }, 324 325 /** 326 * Get resource file data from zip file 327 * @function 328 * @param {String} pszZipFilePath 329 * @param {String} fileName fileName The resource file name which contain the relative path of zip file 330 * @param {Number} size size If get the file data succeed the it will be the data size,or it will be 0 331 * @warning If you get the file data succeed,you must delete it after used. 332 * @deprecated 333 */ 334 getFileDataFromZip:function (pszZipFilePath, fileName, size) { 335 }, 336 337 /** 338 * removes the HD suffix from a path 339 * @function 340 * @param {String} path 341 * @deprecated 342 */ 343 removeSuffixFromFile:function (path) { 344 }, 345 346 ////////////////////////////////////////////////////////////////////////// 347 // Notification support when getByteArrayFromFile from invalid file path. 348 ////////////////////////////////////////////////////////////////////////// 349 /** 350 * Notification support when getByteArrayFromFile from invalid file path. 351 * @function 352 * @type {Boolean} 353 */ 354 popupNotify:true, 355 356 /** 357 * Generate the absolute path of the file. 358 * @function 359 * @param {String} pszRelativePath 360 * @return {String} The absolute path of the file. 361 * @warning We only add the ResourcePath before the relative path of the file. <br/> 362 * If you have not set the ResourcePath,the function add "/NEWPLUS/TDA_DATA/UserData/" as default.<br/> 363 * You can set ResourcePath by function void setResourcePath(const char *resourcePath); 364 */ 365 fullPathFromRelativePath:function (pszRelativePath) { 366 return pszRelativePath; 367 }, 368 369 /** 370 * <p> 371 * Returns the fullpath for a given filename. </br> 372 * First it will try to get a new filename from the "filenameLookup" dictionary. </br> 373 * If a new filename can't be found on the dictionary, it will use the original filename. </br> 374 * Then it will try obtain the full path of the filename using the CCFileUtils search rules: resources directory and search paths. </br> 375 * The file search is based on the array element order of search paths and resolution directories. </br> 376 * </br> 377 * For instance: </br> 378 * </br> 379 * We set two elements("/mnt/sdcard/", "internal_dir/") to search paths vector by setSearchPaths, </br> 380 * and set three elements("resources-ipadhd/", "resources-ipad/", "resources-iphonehd") </br> 381 * to resolutions vector by setSearchResolutionsOrder. The "internal_dir" is relative to "Resources/". </br> 382 * </br> 383 * If we have a file named 'sprite.png', the mapping in fileLookup dictionary contains `key: sprite.png -> value: sprite.pvr.gz`. </br> 384 * Firstly, it will replace 'sprite.png' with 'sprite.pvr.gz', then searching the file sprite.pvr.gz as follows: </br> 385 * /mnt/sdcard/resources-ipadhd/sprite.pvr.gz (if not found, search next) </br> 386 * /mnt/sdcard/resources-ipad/sprite.pvr.gz (if not found, search next) </br> 387 * /mnt/sdcard/resources-iphonehd/sprite.pvr.gz (if not found, search next) </br> 388 * /mnt/sdcard/sprite.pvr.gz (if not found, search next) </br> 389 * internal_dir/resources-ipadhd/sprite.pvr.gz (if not found, search next) </br> 390 * internal_dir/resources-ipad/sprite.pvr.gz (if not found, search next) </br> 391 * internal_dir/resources-iphonehd/sprite.pvr.gz (if not found, search next) </br> 392 * internal_dir/sprite.pvr.gz (if not found, return "sprite.png") </br> 393 * </br> 394 * If the filename contains relative path like "gamescene/uilayer/sprite.png", </br> 395 * and the mapping in fileLookup dictionary contains `key: gamescene/uilayer/sprite.png -> value: gamescene/uilayer/sprite.pvr.gz`. </br> 396 * The file search order will be: </br> 397 * /mnt/sdcard/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next) </br> 398 * /mnt/sdcard/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next) </br> 399 * /mnt/sdcard/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next) </br> 400 * /mnt/sdcard/gamescene/uilayer/sprite.pvr.gz (if not found, search next) </br> 401 * internal_dir/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next) </br> 402 * internal_dir/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next) </br> 403 * internal_dir/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next) </br> 404 * internal_dir/gamescene/uilayer/sprite.pvr.gz (if not found, return "gamescene/uilayer/sprite.png") </br> 405 * </br> 406 * If the new file can't be found on the file system, it will return the parameter pszFileName directly. </br> 407 * </br> 408 * This method was added to simplify multiplatform support. Whether you are using cocos2d-js or any cross-compilation toolchain like StellaSDK or Apportable, </br> 409 * you might need to load different resources for a given file in the different platforms. 410 * </p> 411 * @param {String} filename 412 * @return {String} full path for a given filename. 413 */ 414 fullPathForFilename:function (filename) { 415 var found = false; 416 417 var newFileName = this._getNewFilename(filename); 418 var fullPath; 419 420 if (newFileName && newFileName.length > 1 && (newFileName.indexOf(":") == 1)) 421 return newFileName; 422 423 for (var i = 0; i < this._searchPathArray.length; i++) { 424 var searchPath = this._searchPathArray[i]; 425 for (var j = 0; j < this._searchResolutionsOrderArray.length; j++) { 426 var resourceDirectory = this._searchResolutionsOrderArray[j]; 427 fullPath = this._getPathForFilename(newFileName, resourceDirectory, searchPath); 428 if (fullPath) { 429 found = true; 430 break; 431 } 432 } 433 if (found) 434 break; 435 } 436 437 return found ? fullPath : newFileName; 438 }, 439 440 /** 441 * <p> 442 * Loads the filenameLookup dictionary from the contents of a filename. <br/> 443 * <br/> 444 * @note The plist file name should follow the format below: <br/> 445 * <?xml version="1.0" encoding="UTF-8"?> <br/> 446 * <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <br/> 447 * <plist version="1.0"> <br/> 448 * <dict> <br/> 449 * <key>filenames</key> <br/> 450 * <dict> <br/> 451 * <key>sounds/click.wav</key> <br/> 452 * <string>sounds/click.caf</string> <br/> 453 * <key>sounds/endgame.wav</key> <br/> 454 * <string>sounds/endgame.caf</string> <br/> 455 * <key>sounds/gem-0.wav</key> <br/> 456 * <string>sounds/gem-0.caf</string> <br/> 457 * </dict> <br/> 458 * <key>metadata</key> <br/> 459 * <dict> <br/> 460 * <key>version</key> <br/> 461 * <integer>1</integer> <br/> 462 * </dict> <br/> 463 * </dict> <br/> 464 * </plist> <br/> 465 * </p> 466 * @param {String} filename The plist file name. 467 */ 468 loadFilenameLookup:function (filename) { 469 var fullPath = this.fullPathForFilename(filename); 470 if (fullPath.length > 0) { 471 var dict = cc.SAXParser.getInstance().parse(fullPath); 472 var metadataDict = dict["metadata"]; 473 var version = parseInt(metadataDict["version"]); 474 if (version != 1) { 475 cc.log("cocos2d: ERROR: Invalid filenameLookup dictionary version: " + version + ". Filename: " + filename); 476 return; 477 } 478 this.setFilenameLookupDictionary(dict["filenames"]); 479 } 480 }, 481 482 /** 483 * Sets the filenameLookup dictionary. 484 * @param {Object} filenameLookupDict The dictionary for replacing filename. 485 */ 486 setFilenameLookupDictionary:function (filenameLookupDict) { 487 this._filenameLookupDict = filenameLookupDict; 488 }, 489 490 /** 491 * Gets full path from a file name and the path of the reletive file. 492 * @param {String} filename The file name. 493 * @param {String} relativeFile The path of the relative file. 494 * @return {String} The full path. 495 */ 496 fullPathFromRelativeFile:function (filename, relativeFile) { 497 var tmpPath; 498 if (filename) { 499 tmpPath = relativeFile.substring(0, relativeFile.lastIndexOf("/") + 1); 500 return tmpPath + filename; 501 } 502 else { 503 tmpPath = relativeFile.substring(0, relativeFile.lastIndexOf(".")); 504 tmpPath = tmpPath + ".png"; 505 return tmpPath; 506 } 507 }, 508 509 /** 510 * <p> 511 * Sets the array that contains the search order of the resources. 512 * </p> 513 * @see getSearchResolutionsOrder(void), fullPathForFilename(const char*). 514 * @param {Array} searchResolutionsOrder 515 */ 516 setSearchResolutionsOrder:function (searchResolutionsOrder) { 517 this._searchResolutionsOrderArray = searchResolutionsOrder; 518 }, 519 520 /** 521 * Gets the array that contains the search order of the resources. 522 * @see setSearchResolutionsOrder(), fullPathForFilename(const char*). 523 * @return {Array} 524 */ 525 getSearchResolutionsOrder:function () { 526 return this._searchResolutionsOrderArray; 527 }, 528 529 /** 530 * <p> 531 * Array of search paths. <br/> 532 * You can use this array to modify the search path of the resources. <br/> 533 * If you want to use "themes" or search resources in the "cache", you can do it easily by adding new entries in this array. <br/> 534 * <br/> 535 * By default it is an array with only the "" (empty string) element. <br/> 536 * </p> 537 * @param {Array} searchPaths 538 */ 539 setSearchPath:function (searchPaths) { 540 this._searchPathArray = searchPaths; 541 }, 542 543 /** 544 * return Array of search paths. 545 * @return {Array} 546 */ 547 getSearchPath:function () { 548 return this._searchPathArray; 549 }, 550 551 getResourceDirectory:function () { 552 return this._directory; 553 }, 554 555 556 /** 557 * Set the ResourcePath,we will find resource in this path 558 * @function 559 * @param {String} resourcePath The absolute resource path 560 * @warning Don't call this function in android and iOS, it has not effect.<br/> 561 * In android, if you want to read file other than apk, you shoud use invoke getByteArrayFromFile(), and pass the<br/> 562 * absolute path. 563 * @deprecated 564 */ 565 setResourcePath:function (resourcePath) { 566 }, 567 568 /** 569 * Generate an Dictionary of object by file 570 * @deprecated 571 * @param fileName The file name of *.plist file 572 * @return {object} The Dictionary of object generated from the file 573 */ 574 dictionaryWithContentsOfFile:function (fileName) { 575 cc.log("dictionaryWithContentsOfFile is deprecated. Use createDictionaryWithContentsOfFile instead"); 576 return this.createDictionaryWithContentsOfFile(fileName); 577 }, 578 579 /** 580 * Generate an Dictionary of object by file 581 * @param filename The file name of *.plist file 582 * @return {object} The Dictionary of object generated from the file 583 */ 584 createDictionaryWithContentsOfFile: function(filename){ 585 return cc.SAXParser.getInstance().parse(filename); 586 }, 587 588 /** 589 * get string from file 590 * @function 591 * @param {String} fileName 592 * @return {String} 593 */ 594 getStringFromFile:function (fileName) { 595 return this.getTextFileData(fileName); //cc.SAXParser.getInstance().getList(fileName); 596 }, 597 598 /** 599 * The same meaning as dictionaryWithContentsOfFile(), but it doesn't call autorelease, so the invoker should call release(). 600 * @function 601 * @param {String} fileName 602 * @return {object} The Dictionary of object generated from the file 603 */ 604 dictionaryWithContentsOfFileThreadSafe:function (fileName) { 605 return cc.SAXParser.getInstance().parse(fileName); 606 }, 607 608 /** 609 * Get the writeable path 610 * @return {String} The path that can write/read file 611 * @deprecated 612 */ 613 getWritablePath:function () { 614 return ""; 615 }, 616 617 /** 618 * Set whether pop-up a message box when the image load failed 619 * @param {Boolean} notify 620 */ 621 setPopupNotify:function (notify) { 622 cc.popupNotify = notify; 623 }, 624 625 /** 626 * Get whether pop-up a message box when the image load failed 627 * @return {Boolean} 628 */ 629 isPopupNotify:function () { 630 return cc.popupNotify; 631 }, 632 633 _resourceRootPath:"", 634 getResourceRootPath:function () { 635 return this._resourceRootPath; 636 }, 637 638 setResourceRootPath:function (resourceRootPath) { 639 this._resourceRootPath = resourceRootPath; 640 }, 641 642 /** 643 * Gets the new filename from the filename lookup dictionary. 644 * @param {String} filename 645 * @return {String|null} The new filename after searching in the filename lookup dictionary. If the original filename wasn't in the dictionary, it will return the original filename. 646 * @private 647 */ 648 _getNewFilename:function (filename) { 649 var newFileName = null; 650 var fileNameFound = this._filenameLookupDict ? this._filenameLookupDict[filename] : null; 651 if (!fileNameFound || fileNameFound.length === 0) 652 newFileName = filename; 653 else { 654 newFileName = fileNameFound; 655 cc.log("FOUND NEW FILE NAME: " + newFileName); 656 } 657 return newFileName; 658 }, 659 660 /** 661 * Gets full path for filename, resolution directory and search path. 662 * @param {String} filename 663 * @param {String} resourceDirectory 664 * @param {String} searchPath 665 * @return {String} The full path of the file. It will return an empty string if the full path of the file doesn't exist. 666 * @private 667 */ 668 _getPathForFilename:function (filename, resourceDirectory, searchPath) { 669 var ret; 670 var resourceRootPath = this.getResourceRootPath(); //cc.Application.getInstance().getResourceRootPath(); 671 672 if (filename && (filename.length > 0) && (filename.indexOf('/') === 0 || filename.indexOf("\\") === 0)) { 673 ret = ""; 674 } else if (resourceRootPath.length > 0) { 675 ret = resourceRootPath; 676 if (ret[ret.length - 1] != '\\' && ret[ret.length - 1] != '/') 677 ret += "/"; 678 } else { 679 ret = resourceRootPath; 680 } 681 682 var file = filename; 683 var file_path = ""; 684 var pos = filename.lastIndexOf('/'); 685 if (pos != -1) { 686 file_path = filename.substr(0, pos + 1); 687 file = filename.substr(pos + 1); 688 } 689 var path = searchPath; 690 if (path.length > 0 && path.lastIndexOf('/') !== path.length - 1) 691 path += '/'; 692 path += file_path; 693 path += resourceDirectory; 694 if (path.length > 0 && path.lastIndexOf("/") !== path.length - 1) 695 path += '/'; 696 path += file; 697 ret += path; 698 return ret; 699 }, 700 701 /** 702 * Gets full path for the directory and the filename. 703 * @param {String} directory The directory contains the file we are looking for. 704 * @param {String} fileName The name of the file. 705 * @return {Boolean} The full path of the file, if the file can't be found, it will return an empty string. 706 * @private 707 */ 708 _getFullPathForDirectoryAndFilename:function(directory, fileName){ 709 710 }, 711 712 /** 713 * <p> 714 * Sets the array of search paths. <br/> 715 * <br/> 716 * You can use this array to modify the search path of the resources. <br/> 717 * If you want to use "themes" or search resources in the "cache", you can do it easily by adding new entries in this array. <br/> 718 * <br/> 719 * @note This method could access relative path and absolute path. <br/> 720 * If the relative path was passed to the vector, CCFileUtils will add the default resource directory before the relative path. <br/> 721 * For instance: <br/> 722 * On Android, the default resource root path is "assets/". <br/> 723 * If "/mnt/sdcard/" and "resources-large" were set to the search paths vector, <br/> 724 * "resources-large" will be converted to "assets/resources-large" since it was a relative path. 725 * </p> 726 * @see fullPathForFilename(const char*) 727 * @param {Array} searchPaths The array contains search paths. 728 */ 729 setSearchPaths:function (searchPaths) { 730 var existDefaultRootPath = false; 731 732 this._searchPathArray = []; 733 for (var i = 0; i < searchPaths.length; i++) { 734 var iter = searchPaths[i]; 735 736 var strPrefix; 737 var path; 738 if (!this.isAbsolutePath(iter)) { // Not an absolute path 739 strPrefix = this._defaultResRootPath; 740 } 741 path = strPrefix + iter; 742 if (path.length > 0 && path[path.length - 1] != '/') { 743 path += "/"; 744 } 745 if (!existDefaultRootPath && path == this._defaultResRootPath) { 746 existDefaultRootPath = true; 747 } 748 this._searchPathArray.push(path); 749 } 750 751 if (!existDefaultRootPath) { 752 //cc.log("Default root path doesn't exist, adding it."); 753 this._searchPathArray.push(this._defaultResRootPath); 754 } 755 756 }, 757 758 /** 759 * Add search path. 760 * @param {String} path 761 */ 762 addSearchPath:function (path) { 763 var strPrefix; 764 if (!this.isAbsolutePath(path)) { // Not an absolute path 765 strPrefix = this._defaultResRootPath; 766 } 767 path = strPrefix + path; 768 if (path.length > 0 && path[path.length - 1] != '/') { 769 path += "/"; 770 } 771 this._searchPathArray.push(path); 772 }, 773 774 /** 775 * Gets the array of search paths. 776 * @see fullPathForFilename(const char*). 777 * @return {Array} The array of search paths. 778 */ 779 getSearchPaths:function(){ 780 781 }, 782 783 /** 784 * Checks whether the path is an absolute path. 785 * @param {String} strPath The path that needs to be checked. 786 * @returns {boolean} true if it's an absolute path, otherwise it will return false. 787 */ 788 isAbsolutePath:function (strPath) { 789 return (strPath[0] == '/'); 790 } 791 }); 792 793 cc.s_SharedFileUtils = null; 794 /** 795 * Gets the instance of CCFileUtils. 796 * @returns {cc.FileUtils} 797 */ 798 cc.FileUtils.getInstance = function () { 799 if (cc.s_SharedFileUtils == null) { 800 cc.s_SharedFileUtils = new cc.FileUtils(); 801 } 802 return cc.s_SharedFileUtils; 803 }; 804