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