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.length = 0; 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.onload = function (e) { 206 var fileContents = xhr.responseText; 207 if (fileContents) { 208 selfPointer._fileDataCache[fileUrl] = selfPointer._stringConvertToArray(fileContents); 209 } else { 210 cc.Loader.getInstance().onResLoadingErr(fileUrl); 211 } 212 cc.Loader.getInstance().onResLoaded(); 213 }; 214 } 215 xhr.send(null); 216 }, 217 218 _loadBinaryFileData:function (fileUrl) { 219 var req = this._getXMLHttpRequest(); 220 req.open('GET', fileUrl, false); 221 var arrayInfo = null; 222 if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { 223 req.setRequestHeader("Accept-Charset", "x-user-defined"); 224 req.send(null); 225 if (req.status != 200) 226 return null; 227 228 var fileContents = cc._convertResponseBodyToText(req["responseBody"]); 229 if (fileContents) { 230 arrayInfo = this._stringConvertToArray(fileContents); 231 this._fileDataCache[fileUrl] = arrayInfo; 232 } 233 } else { 234 if (req.overrideMimeType) 235 req.overrideMimeType('text\/plain; charset=x-user-defined'); 236 req.send(null); 237 if (req.status != 200) 238 return null; 239 240 arrayInfo = this._stringConvertToArray(req.responseText); 241 this._fileDataCache[fileUrl] = arrayInfo; 242 } 243 return arrayInfo; 244 }, 245 246 _stringConvertToArray:function (strData) { 247 if (!strData) 248 return null; 249 250 var arrData = new Uint8Array(strData.length); 251 for (var i = 0; i < strData.length; i++) { 252 arrData[i] = strData.charCodeAt(i) & 0xff; 253 } 254 return arrData; 255 }, 256 257 unloadTextFileData:function (fileUrl) { 258 fileUrl = this.fullPathForFilename(fileUrl); 259 if (this._textFileCache.hasOwnProperty(fileUrl)) 260 delete this._textFileCache[fileUrl]; 261 }, 262 263 preloadTextFileData:function (fileUrl) { 264 fileUrl = this.fullPathForFilename(fileUrl); 265 var selfPointer = this; 266 267 var xhr = this._getXMLHttpRequest(); 268 xhr.open("GET", fileUrl, true); 269 if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { 270 // IE-specific logic here 271 xhr.setRequestHeader("Accept-Charset", "utf-8"); 272 xhr.onreadystatechange = function (event) { 273 if (xhr.readyState == 4) { 274 if (xhr.status == 200) { 275 var fileContents = xhr.responseText; 276 if (fileContents) 277 selfPointer._textFileCache[fileUrl] = fileContents; 278 } else { 279 cc.Loader.getInstance().onResLoadingErr(fileUrl); 280 } 281 cc.Loader.getInstance().onResLoaded(); 282 } 283 }; 284 } else { 285 if (xhr.overrideMimeType) 286 xhr.overrideMimeType("text\/plain; charset=utf-8"); 287 xhr.onload = function (e) { 288 if (xhr.responseText) { 289 selfPointer._textFileCache[fileUrl] = xhr.responseText; 290 } else { 291 cc.Loader.getInstance().onResLoadingErr(fileUrl); 292 } 293 cc.Loader.getInstance().onResLoaded(); 294 }; 295 } 296 xhr.send(null); 297 }, 298 299 _loadTextFileData:function (fileUrl) { 300 var req = this._getXMLHttpRequest(); 301 req.open('GET', fileUrl, false); 302 var fileContents = null; 303 if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { 304 req.setRequestHeader("Accept-Charset", "utf-8"); 305 } else { 306 if (req.overrideMimeType) 307 req.overrideMimeType('text\/plain; charset=utf-8'); 308 } 309 req.send(null); 310 if (req.status != 200) 311 return null; 312 313 fileContents = req.responseText; 314 if (fileContents) { 315 this._textFileCache[fileUrl] = fileContents; 316 } 317 return fileContents; 318 }, 319 320 /** 321 * Gets resource file data 322 * @param {String} fileUrl The resource file name which contains the path. 323 * @returns {String} 324 */ 325 getTextFileData:function (fileUrl) { 326 fileUrl = this.fullPathForFilename(fileUrl); 327 if (this._textFileCache.hasOwnProperty(fileUrl)) 328 return this._textFileCache[fileUrl]; 329 return this._loadTextFileData(fileUrl); 330 }, 331 332 /** 333 * Get resource file data from zip file 334 * @function 335 * @param {String} pszZipFilePath 336 * @param {String} fileName fileName The resource file name which contain the relative path of zip file 337 * @param {Number} size size If get the file data succeed the it will be the data size,or it will be 0 338 * @warning If you get the file data succeed,you must delete it after used. 339 * @deprecated 340 */ 341 getFileDataFromZip:function (pszZipFilePath, fileName, size) { 342 }, 343 344 /** 345 * removes the HD suffix from a path 346 * @function 347 * @param {String} path 348 * @deprecated 349 */ 350 removeSuffixFromFile:function (path) { 351 }, 352 353 ////////////////////////////////////////////////////////////////////////// 354 // Notification support when getByteArrayFromFile from invalid file path. 355 ////////////////////////////////////////////////////////////////////////// 356 /** 357 * Notification support when getByteArrayFromFile from invalid file path. 358 * @function 359 * @type {Boolean} 360 */ 361 popupNotify:true, 362 363 /** 364 * Generate the absolute path of the file. 365 * @function 366 * @param {String} pszRelativePath 367 * @return {String} The absolute path of the file. 368 * @warning We only add the ResourcePath before the relative path of the file. <br/> 369 * If you have not set the ResourcePath,the function add "/NEWPLUS/TDA_DATA/UserData/" as default.<br/> 370 * You can set ResourcePath by function void setResourcePath(const char *resourcePath); 371 */ 372 fullPathFromRelativePath:function (pszRelativePath) { 373 return pszRelativePath; 374 }, 375 376 /** 377 * <p> 378 * Returns the fullpath for a given filename. </br> 379 * First it will try to get a new filename from the "filenameLookup" dictionary. </br> 380 * If a new filename can't be found on the dictionary, it will use the original filename. </br> 381 * Then it will try obtain the full path of the filename using the CCFileUtils search rules: resources directory and search paths. </br> 382 * The file search is based on the array element order of search paths and resolution directories. </br> 383 * </br> 384 * For instance: </br> 385 * </br> 386 * We set two elements("/mnt/sdcard/", "internal_dir/") to search paths vector by setSearchPaths, </br> 387 * and set three elements("resources-ipadhd/", "resources-ipad/", "resources-iphonehd") </br> 388 * to resolutions vector by setSearchResolutionsOrder. The "internal_dir" is relative to "Resources/". </br> 389 * </br> 390 * If we have a file named 'sprite.png', the mapping in fileLookup dictionary contains `key: sprite.png -> value: sprite.pvr.gz`. </br> 391 * Firstly, it will replace 'sprite.png' with 'sprite.pvr.gz', then searching the file sprite.pvr.gz as follows: </br> 392 * /mnt/sdcard/resources-ipadhd/sprite.pvr.gz (if not found, search next) </br> 393 * /mnt/sdcard/resources-ipad/sprite.pvr.gz (if not found, search next) </br> 394 * /mnt/sdcard/resources-iphonehd/sprite.pvr.gz (if not found, search next) </br> 395 * /mnt/sdcard/sprite.pvr.gz (if not found, search next) </br> 396 * internal_dir/resources-ipadhd/sprite.pvr.gz (if not found, search next) </br> 397 * internal_dir/resources-ipad/sprite.pvr.gz (if not found, search next) </br> 398 * internal_dir/resources-iphonehd/sprite.pvr.gz (if not found, search next) </br> 399 * internal_dir/sprite.pvr.gz (if not found, return "sprite.png") </br> 400 * </br> 401 * If the filename contains relative path like "gamescene/uilayer/sprite.png", </br> 402 * and the mapping in fileLookup dictionary contains `key: gamescene/uilayer/sprite.png -> value: gamescene/uilayer/sprite.pvr.gz`. </br> 403 * The file search order will be: </br> 404 * /mnt/sdcard/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next) </br> 405 * /mnt/sdcard/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next) </br> 406 * /mnt/sdcard/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next) </br> 407 * /mnt/sdcard/gamescene/uilayer/sprite.pvr.gz (if not found, search next) </br> 408 * internal_dir/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next) </br> 409 * internal_dir/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next) </br> 410 * internal_dir/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next) </br> 411 * internal_dir/gamescene/uilayer/sprite.pvr.gz (if not found, return "gamescene/uilayer/sprite.png") </br> 412 * </br> 413 * If the new file can't be found on the file system, it will return the parameter pszFileName directly. </br> 414 * </br> 415 * This method was added to simplify multiplatform support. Whether you are using cocos2d-js or any cross-compilation toolchain like StellaSDK or Apportable, </br> 416 * you might need to load different resources for a given file in the different platforms. 417 * </p> 418 * @param {String} filename 419 * @return {String} full path for a given filename. 420 */ 421 fullPathForFilename:function (filename) { 422 var found = false; 423 424 var newFileName = this._getNewFilename(filename); 425 var fullPath; 426 427 //if (newFileName && newFileName.length > 1) 428 // return newFileName; 429 430 for (var i = 0; i < this._searchPathArray.length; i++) { 431 var searchPath = this._searchPathArray[i]; 432 for (var j = 0; j < this._searchResolutionsOrderArray.length; j++) { 433 var resourceDirectory = this._searchResolutionsOrderArray[j]; 434 fullPath = this._getPathForFilename(newFileName, resourceDirectory, searchPath); 435 if (fullPath) { 436 found = true; 437 break; 438 } 439 } 440 if (found) 441 break; 442 } 443 444 return found ? fullPath : newFileName; 445 }, 446 447 /** 448 * <p> 449 * Loads the filenameLookup dictionary from the contents of a filename. <br/> 450 * <br/> 451 * @note The plist file name should follow the format below: <br/> 452 * <?xml version="1.0" encoding="UTF-8"?> <br/> 453 * <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <br/> 454 * <plist version="1.0"> <br/> 455 * <dict> <br/> 456 * <key>filenames</key> <br/> 457 * <dict> <br/> 458 * <key>sounds/click.wav</key> <br/> 459 * <string>sounds/click.caf</string> <br/> 460 * <key>sounds/endgame.wav</key> <br/> 461 * <string>sounds/endgame.caf</string> <br/> 462 * <key>sounds/gem-0.wav</key> <br/> 463 * <string>sounds/gem-0.caf</string> <br/> 464 * </dict> <br/> 465 * <key>metadata</key> <br/> 466 * <dict> <br/> 467 * <key>version</key> <br/> 468 * <integer>1</integer> <br/> 469 * </dict> <br/> 470 * </dict> <br/> 471 * </plist> <br/> 472 * </p> 473 * @param {String} filename The plist file name. 474 */ 475 loadFilenameLookup:function (filename) { 476 var fullPath = this.fullPathForFilename(filename); 477 if (fullPath.length > 0) { 478 var dict = cc.SAXParser.getInstance().parse(fullPath); 479 var metadataDict = dict["metadata"]; 480 var version = parseInt(metadataDict["version"]); 481 if (version != 1) { 482 cc.log("cocos2d: ERROR: Invalid filenameLookup dictionary version: " + version + ". Filename: " + filename); 483 return; 484 } 485 this.setFilenameLookupDictionary(dict["filenames"]); 486 } 487 }, 488 489 /** 490 * Sets the filenameLookup dictionary. 491 * @param {Object} filenameLookupDict The dictionary for replacing filename. 492 */ 493 setFilenameLookupDictionary:function (filenameLookupDict) { 494 this._filenameLookupDict = filenameLookupDict; 495 }, 496 497 /** 498 * Gets full path from a file name and the path of the reletive file. 499 * @param {String} filename The file name. 500 * @param {String} relativeFile The path of the relative file. 501 * @return {String} The full path. 502 */ 503 fullPathFromRelativeFile:function (filename, relativeFile) { 504 var tmpPath; 505 if (filename) { 506 tmpPath = relativeFile.substring(0, relativeFile.lastIndexOf("/") + 1); 507 return tmpPath + filename; 508 } 509 else { 510 tmpPath = relativeFile.substring(0, relativeFile.lastIndexOf(".")); 511 tmpPath = tmpPath + ".png"; 512 return tmpPath; 513 } 514 }, 515 516 /** 517 * <p> 518 * Sets the array that contains the search order of the resources. 519 * </p> 520 * @see getSearchResolutionsOrder(void), fullPathForFilename(const char*). 521 * @param {Array} searchResolutionsOrder 522 */ 523 setSearchResolutionsOrder:function (searchResolutionsOrder) { 524 this._searchResolutionsOrderArray = searchResolutionsOrder; 525 }, 526 527 /** 528 * Gets the array that contains the search order of the resources. 529 * @see setSearchResolutionsOrder(), fullPathForFilename(const char*). 530 * @return {Array} 531 */ 532 getSearchResolutionsOrder:function () { 533 return this._searchResolutionsOrderArray; 534 }, 535 536 /** 537 * <p> 538 * Array of search paths. <br/> 539 * You can use this array to modify the search path of the resources. <br/> 540 * 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/> 541 * <br/> 542 * By default it is an array with only the "" (empty string) element. <br/> 543 * </p> 544 * @param {Array} searchPaths 545 */ 546 setSearchPath:function (searchPaths) { 547 this._searchPathArray = searchPaths; 548 }, 549 550 /** 551 * return Array of search paths. 552 * @return {Array} 553 */ 554 getSearchPath:function () { 555 return this._searchPathArray; 556 }, 557 558 getResourceDirectory:function () { 559 return this._directory; 560 }, 561 562 563 /** 564 * Set the ResourcePath,we will find resource in this path 565 * @function 566 * @param {String} resourcePath The absolute resource path 567 * @warning Don't call this function in android and iOS, it has not effect.<br/> 568 * In android, if you want to read file other than apk, you shoud use invoke getByteArrayFromFile(), and pass the<br/> 569 * absolute path. 570 * @deprecated 571 */ 572 setResourcePath:function (resourcePath) { 573 }, 574 575 /** 576 * Generate an Dictionary of object by file 577 * @deprecated 578 * @param fileName The file name of *.plist file 579 * @return {object} The Dictionary of object generated from the file 580 */ 581 dictionaryWithContentsOfFile:function (fileName) { 582 cc.log("dictionaryWithContentsOfFile is deprecated. Use createDictionaryWithContentsOfFile instead"); 583 return this.createDictionaryWithContentsOfFile(fileName); 584 }, 585 586 /** 587 * Generate an Dictionary of object by file 588 * @param filename The file name of *.plist file 589 * @return {object} The Dictionary of object generated from the file 590 */ 591 createDictionaryWithContentsOfFile: function(filename){ 592 return cc.SAXParser.getInstance().parse(filename); 593 }, 594 595 /** 596 * get string from file 597 * @function 598 * @param {String} fileName 599 * @return {String} 600 */ 601 getStringFromFile:function (fileName) { 602 return this.getTextFileData(fileName); //cc.SAXParser.getInstance().getList(fileName); 603 }, 604 605 /** 606 * The same meaning as dictionaryWithContentsOfFile(), but it doesn't call autorelease, so the invoker should call release(). 607 * @function 608 * @param {String} fileName 609 * @return {object} The Dictionary of object generated from the file 610 */ 611 dictionaryWithContentsOfFileThreadSafe:function (fileName) { 612 return cc.SAXParser.getInstance().parse(fileName); 613 }, 614 615 /** 616 * Get the writeable path 617 * @return {String} The path that can write/read file 618 * @deprecated 619 */ 620 getWritablePath:function () { 621 return ""; 622 }, 623 624 /** 625 * Set whether pop-up a message box when the image load failed 626 * @param {Boolean} notify 627 */ 628 setPopupNotify:function (notify) { 629 cc.popupNotify = notify; 630 }, 631 632 /** 633 * Get whether pop-up a message box when the image load failed 634 * @return {Boolean} 635 */ 636 isPopupNotify:function () { 637 return cc.popupNotify; 638 }, 639 640 _resourceRootPath:"", 641 getResourceRootPath:function () { 642 return this._resourceRootPath; 643 }, 644 645 setResourceRootPath:function (resourceRootPath) { 646 this._resourceRootPath = resourceRootPath; 647 }, 648 649 /** 650 * Gets the new filename from the filename lookup dictionary. 651 * @param {String} filename 652 * @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. 653 * @private 654 */ 655 _getNewFilename:function (filename) { 656 var newFileName = null; 657 var fileNameFound = this._filenameLookupDict ? this._filenameLookupDict[filename] : null; 658 if (!fileNameFound || fileNameFound.length === 0) 659 newFileName = filename; 660 else { 661 newFileName = fileNameFound; 662 cc.log("FOUND NEW FILE NAME: " + newFileName); 663 } 664 return newFileName; 665 }, 666 667 /** 668 * Gets full path for filename, resolution directory and search path. 669 * @param {String} filename 670 * @param {String} resourceDirectory 671 * @param {String} searchPath 672 * @return {String} The full path of the file. It will return an empty string if the full path of the file doesn't exist. 673 * @private 674 */ 675 _getPathForFilename:function (filename, resourceDirectory, searchPath) { 676 var ret; 677 var resourceRootPath = this.getResourceRootPath(); //cc.Application.getInstance().getResourceRootPath(); 678 679 if (filename && (filename.length > 0) && (filename.indexOf('/') === 0 || filename.indexOf("\\") === 0)) { 680 ret = ""; 681 } else if (resourceRootPath.length > 0) { 682 ret = resourceRootPath; 683 if (ret[ret.length - 1] != '\\' && ret[ret.length - 1] != '/') 684 ret += "/"; 685 } else { 686 ret = resourceRootPath; 687 } 688 689 var file = filename; 690 var file_path = ""; 691 var pos = filename.lastIndexOf('/'); 692 if (pos != -1) { 693 file_path = filename.substr(0, pos + 1); 694 file = filename.substr(pos + 1); 695 } 696 var path = searchPath; 697 if (path.length > 0 && path.lastIndexOf('/') !== path.length - 1) 698 path += '/'; 699 path += file_path; 700 path += resourceDirectory; 701 if (path.length > 0 && path.lastIndexOf("/") !== path.length - 1) 702 path += '/'; 703 path += file; 704 ret += path; 705 return ret; 706 }, 707 708 /** 709 * Gets full path for the directory and the filename. 710 * @param {String} directory The directory contains the file we are looking for. 711 * @param {String} fileName The name of the file. 712 * @return {Boolean} The full path of the file, if the file can't be found, it will return an empty string. 713 * @private 714 */ 715 _getFullPathForDirectoryAndFilename:function(directory, fileName){ 716 717 }, 718 719 /** 720 * <p> 721 * Sets the array of search paths. <br/> 722 * <br/> 723 * You can use this array to modify the search path of the resources. <br/> 724 * 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/> 725 * <br/> 726 * @note This method could access relative path and absolute path. <br/> 727 * If the relative path was passed to the vector, CCFileUtils will add the default resource directory before the relative path. <br/> 728 * For instance: <br/> 729 * On Android, the default resource root path is "assets/". <br/> 730 * If "/mnt/sdcard/" and "resources-large" were set to the search paths vector, <br/> 731 * "resources-large" will be converted to "assets/resources-large" since it was a relative path. 732 * </p> 733 * @see fullPathForFilename(const char*) 734 * @param {Array} searchPaths The array contains search paths. 735 */ 736 setSearchPaths:function (searchPaths) { 737 var existDefaultRootPath = false; 738 739 var locPathArray = this._searchPathArray; 740 locPathArray.length = 0; 741 for (var i = 0; i < searchPaths.length; i++) { 742 var iter = searchPaths[i]; 743 744 var strPrefix; 745 var path; 746 if (!this.isAbsolutePath(iter)) { // Not an absolute path 747 strPrefix = this._defaultResRootPath; 748 } 749 path = strPrefix + iter; 750 if (path.length > 0 && path[path.length - 1] != '/') { 751 path += "/"; 752 } 753 if (!existDefaultRootPath && path == this._defaultResRootPath) { 754 existDefaultRootPath = true; 755 } 756 locPathArray.push(path); 757 } 758 759 if (!existDefaultRootPath) { 760 //cc.log("Default root path doesn't exist, adding it."); 761 locPathArray.push(this._defaultResRootPath); 762 } 763 }, 764 765 /** 766 * Add search path. 767 * @param {String} path 768 */ 769 addSearchPath:function (path) { 770 var strPrefix; 771 if (!this.isAbsolutePath(path)) { // Not an absolute path 772 strPrefix = this._defaultResRootPath; 773 } 774 path = strPrefix + path; 775 if (path.length > 0 && path[path.length - 1] != '/') { 776 path += "/"; 777 } 778 this._searchPathArray.push(path); 779 }, 780 781 /** 782 * Gets the array of search paths. 783 * @see fullPathForFilename(const char*). 784 * @return {Array} The array of search paths. 785 */ 786 getSearchPaths:function(){ 787 788 }, 789 790 /** 791 * Checks whether the path is an absolute path. 792 * @param {String} strPath The path that needs to be checked. 793 * @returns {boolean} true if it's an absolute path, otherwise it will return false. 794 */ 795 isAbsolutePath:function (strPath) { 796 return (strPath[0] == '/'); 797 } 798 }); 799 800 cc.s_SharedFileUtils = null; 801 /** 802 * Gets the instance of CCFileUtils. 803 * @returns {cc.FileUtils} 804 */ 805 cc.FileUtils.getInstance = function () { 806 if (cc.s_SharedFileUtils == null) { 807 cc.s_SharedFileUtils = new cc.FileUtils(); 808 } 809 return cc.s_SharedFileUtils; 810 }; 811