diff --git a/CocosDenshion/android/Android.mk b/CocosDenshion/android/Android.mk index 200d378a5a..e2dc6250da 100644 --- a/CocosDenshion/android/Android.mk +++ b/CocosDenshion/android/Android.mk @@ -15,6 +15,7 @@ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../include LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include \ $(LOCAL_PATH)/../../cocos2dx \ $(LOCAL_PATH)/../../cocos2dx/include \ + $(LOCAL_PATH)/../../cocos2dx/kazmath/include \ $(LOCAL_PATH)/../../cocos2dx/platform/android LOCAL_CFLAGS += -Wno-psabi diff --git a/CocosDenshion/android/SimpleAudioEngine.cpp b/CocosDenshion/android/SimpleAudioEngine.cpp index 0949f997ed..e0a423dce0 100644 --- a/CocosDenshion/android/SimpleAudioEngine.cpp +++ b/CocosDenshion/android/SimpleAudioEngine.cpp @@ -26,6 +26,7 @@ THE SOFTWARE. #include "jni/SimpleAudioEngineJni.h" #include "opensl/SimpleAudioEngineOpenSL.h" +#include "cocos2d.h" #include #include #include @@ -37,109 +38,13 @@ THE SOFTWARE. static bool s_bI9100 = false; +USING_NS_CC; /********************************************************************************** * jni **********************************************************************************/ #define CLASS_NAME "org/cocos2dx/lib/Cocos2dxHelper" #define METHOD_NAME "getDeviceModel" -typedef struct JniMethodInfo_ -{ - JNIEnv * env; - jclass classID; - jmethodID methodID; -} JniMethodInfo; - -extern "C" { - static JNIEnv* getJNIEnv(void) - { - - JavaVM* jvm = cocos2d::JniHelper::getJavaVM(); - if (NULL == jvm) { - LOGD("Failed to get JNIEnv. JniHelper::getJavaVM() is NULL"); - return NULL; - } - - JNIEnv *env = NULL; - // get jni environment - jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4); - - switch (ret) { - case JNI_OK : - // Success! - return env; - - case JNI_EDETACHED : - // Thread not attached - - // TODO : If calling AttachCurrentThread() on a native thread - // must call DetachCurrentThread() in future. - // see: http://developer.android.com/guide/practices/design/jni.html - - if (jvm->AttachCurrentThread(&env, NULL) < 0) - { - LOGD("Failed to get the environment using AttachCurrentThread()"); - return NULL; - } else { - // Success : Attached and obtained JNIEnv! - return env; - } - - case JNI_EVERSION : - // Cannot recover from this error - LOGD("JNI interface version 1.4 not supported"); - default : - LOGD("Failed to get the environment using GetEnv()"); - return NULL; - } - } - - static jclass getClassID(JNIEnv *pEnv) - { - jclass ret = pEnv->FindClass(CLASS_NAME); - if (! ret) - { - LOGD("Failed to find class of %s", CLASS_NAME); - } - - return ret; - } - - static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *methodName, const char *paramCode) - { - jmethodID methodID = 0; - JNIEnv *pEnv = 0; - bool bRet = false; - - do - { - pEnv = getJNIEnv(); - if (! pEnv) - { - break; - } - - jclass classID = getClassID(pEnv); - - methodID = pEnv->GetStaticMethodID(classID, methodName, paramCode); - if (! methodID) - { - LOGD("Failed to find static method id of %s", methodName); - break; - } - - methodinfo.classID = classID; - methodinfo.env = pEnv; - methodinfo.methodID = methodID; - - bRet = true; - } while (0); - - return bRet; - } -}; - - namespace CocosDenshion { static SimpleAudioEngine *s_pEngine = 0; @@ -148,7 +53,7 @@ SimpleAudioEngine::SimpleAudioEngine() { JniMethodInfo methodInfo; jstring jstr; - if (getStaticMethodInfo(methodInfo, METHOD_NAME, "()Ljava/lang/String;")) + if (JniHelper::getStaticMethodInfo(methodInfo, CLASS_NAME, METHOD_NAME, "()Ljava/lang/String;")) { jstr = (jstring)methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID); } @@ -200,12 +105,16 @@ void SimpleAudioEngine::end() void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath) { - preloadBackgroundMusicJNI(pszFilePath); + // Changing file path to full path + const char* fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath); + preloadBackgroundMusicJNI(fullPath); } void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop) { - playBackgroundMusicJNI(pszFilePath, bLoop); + // Changing file path to full path + const char* fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath); + playBackgroundMusicJNI(fullPath, bLoop); } void SimpleAudioEngine::stopBackgroundMusic(bool bReleaseData) @@ -274,13 +183,15 @@ void SimpleAudioEngine::setEffectsVolume(float volume) unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop) { + // Changing file path to full path + const char* fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath); if (s_bI9100) { - return SimpleAudioEngineOpenSL::sharedEngine()->playEffect(pszFilePath, bLoop); + return SimpleAudioEngineOpenSL::sharedEngine()->playEffect(fullPath, bLoop); } else { - return playEffectJNI(pszFilePath, bLoop); + return playEffectJNI(fullPath, bLoop); } } @@ -298,25 +209,31 @@ void SimpleAudioEngine::stopEffect(unsigned int nSoundId) void SimpleAudioEngine::preloadEffect(const char* pszFilePath) { + // Changing file path to full path + const char* fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath); + if (s_bI9100) { - SimpleAudioEngineOpenSL::sharedEngine()->preloadEffect(pszFilePath); + SimpleAudioEngineOpenSL::sharedEngine()->preloadEffect(fullPath); } else { - preloadEffectJNI(pszFilePath); + preloadEffectJNI(fullPath); } } void SimpleAudioEngine::unloadEffect(const char* pszFilePath) { + // Changing file path to full path + const char* fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath); + if (s_bI9100) { - SimpleAudioEngineOpenSL::sharedEngine()->unloadEffect(pszFilePath); + SimpleAudioEngineOpenSL::sharedEngine()->unloadEffect(fullPath); } else { - unloadEffectJNI(pszFilePath); + unloadEffectJNI(fullPath); } } diff --git a/CocosDenshion/ios/SimpleAudioEngine.mm b/CocosDenshion/ios/SimpleAudioEngine.mm index 24e5a5f9ab..adb5a853d9 100644 --- a/CocosDenshion/ios/SimpleAudioEngine.mm +++ b/CocosDenshion/ios/SimpleAudioEngine.mm @@ -24,6 +24,8 @@ THE SOFTWARE. #include "SimpleAudioEngine.h" #include "SimpleAudioEngine_objc.h" +#include "cocos2d.h" +USING_NS_CC; static void static_end() { @@ -174,12 +176,16 @@ void SimpleAudioEngine::end() void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath) { - static_preloadBackgroundMusic(pszFilePath); + // Changing file path to full path + const char* fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath); + static_preloadBackgroundMusic(fullPath); } void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop) { - static_playBackgroundMusic(pszFilePath, bLoop); + // Changing file path to full path + const char* fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath); + static_playBackgroundMusic(fullPath, bLoop); } void SimpleAudioEngine::stopBackgroundMusic(bool bReleaseData) @@ -224,32 +230,38 @@ void SimpleAudioEngine::setBackgroundMusicVolume(float volume) float SimpleAudioEngine::getEffectsVolume() { - return static_getEffectsVolume(); + return static_getEffectsVolume(); } void SimpleAudioEngine::setEffectsVolume(float volume) { - static_setEffectsVolume(volume); + static_setEffectsVolume(volume); } unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop) { - return static_playEffect(pszFilePath, bLoop); + // Changing file path to full path + const char* fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath); + return static_playEffect(fullPath, bLoop); } void SimpleAudioEngine::stopEffect(unsigned int nSoundId) { - static_stopEffect(nSoundId); + static_stopEffect(nSoundId); } void SimpleAudioEngine::preloadEffect(const char* pszFilePath) { - static_preloadEffect(pszFilePath); + // Changing file path to full path + const char* fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath); + static_preloadEffect(fullPath); } void SimpleAudioEngine::unloadEffect(const char* pszFilePath) { - static_unloadEffect(pszFilePath); + // Changing file path to full path + const char* fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath); + static_unloadEffect(fullPath); } void SimpleAudioEngine::pauseEffect(unsigned int uSoundId) diff --git a/CocosDenshion/proj.win32/CocosDenshion.vcxproj b/CocosDenshion/proj.win32/CocosDenshion.vcxproj index 63281b47b4..278b17fc73 100644 --- a/CocosDenshion/proj.win32/CocosDenshion.vcxproj +++ b/CocosDenshion/proj.win32/CocosDenshion.vcxproj @@ -65,7 +65,7 @@ Disabled - $(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\include;..\Include;%(AdditionalIncludeDirectories) + $(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\include;..\Include;"$(ProjectDir)..\..\cocos2dx";"$(ProjectDir)..\..\cocos2dx\include";"$(ProjectDir)..\..\cocos2dx\kazmath\include";"$(ProjectDir)..\..\cocos2dx\platform\win32";"$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\OGLES";%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;COCOSDENSHIONWIN32_EXPORTS;_EXPORT_DLL_;%(PreprocessorDefinitions) true EnableFastChecks @@ -74,28 +74,31 @@ Level3 EditAndContinue + 4251 - winmm.lib;%(AdditionalDependencies) + winmm.lib;libcocos2d.lib;%(AdditionalDependencies) $(OutDir)$(ProjectName).dll true Windows $(TargetDir)$(TargetName).lib MachineX86 + $(OutDir) - $(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\include;..\Include;%(AdditionalIncludeDirectories) + $(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\include;..\Include;"$(ProjectDir)..\..\cocos2dx";"$(ProjectDir)..\..\cocos2dx\include";"$(ProjectDir)..\..\cocos2dx\kazmath\include";"$(ProjectDir)..\..\cocos2dx\platform\win32";"$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\OGLES";%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;COCOSDENSHIONWIN32_EXPORTS;_EXPORT_DLL_;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase + 4251 - winmm.lib;%(AdditionalDependencies) + winmm.lib;libcocos2d.lib;%(AdditionalDependencies) $(OutDir)$(ProjectName).dll true Windows @@ -103,6 +106,7 @@ true $(TargetDir)$(TargetName).lib MachineX86 + $(OutDir) diff --git a/CocosDenshion/win32/MciPlayer.h b/CocosDenshion/win32/MciPlayer.h index 49dbd93145..730faf15fa 100644 --- a/CocosDenshion/win32/MciPlayer.h +++ b/CocosDenshion/win32/MciPlayer.h @@ -1,7 +1,7 @@ #ifndef _MCI_PLAYER_WIN32_H_ #define _MCI_PLAYER_WIN32_H_ -#include +#include "CCStdC.h" #include namespace CocosDenshion { diff --git a/CocosDenshion/win32/SimpleAudioEngine.cpp b/CocosDenshion/win32/SimpleAudioEngine.cpp index cafe899d6a..3f09d7c651 100644 --- a/CocosDenshion/win32/SimpleAudioEngine.cpp +++ b/CocosDenshion/win32/SimpleAudioEngine.cpp @@ -4,6 +4,8 @@ #include #include "MciPlayer.h" +#include "cocos2d.h" +USING_NS_CC; using namespace std; @@ -72,7 +74,7 @@ void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop) { return; } - + sharedMusic().Open(_FullPath(pszFilePath), _Hash(pszFilePath)); sharedMusic().Play((bLoop) ? -1 : 1); } @@ -255,27 +257,7 @@ void SimpleAudioEngine::setEffectsVolume(float volume) const char * _FullPath(const char * szPath) { - if (! s_szRootPath[0]) - { - WCHAR wszPath[MAX_PATH]; - s_dwRootLen = WideCharToMultiByte(CP_ACP, 0, wszPath, - GetCurrentDirectoryW(sizeof(wszPath), wszPath), - s_szRootPath, MAX_PATH, NULL, NULL); - s_szRootPath[s_dwRootLen] = '\\'; - s_szRootPath[s_dwRootLen + 1] = 0; - strcpy_s(s_szFullPath, sizeof(s_szFullPath), s_szRootPath); - ++s_dwRootLen; - } - - if (0 != szPath[0] && ':' != szPath[1]) - { - strcpy_s(s_szFullPath + s_dwRootLen, sizeof(s_szFullPath) - s_dwRootLen, szPath); - return s_szFullPath; - } - else - { - return szPath; - } + return CCFileUtils::sharedFileUtils()->fullPathForFilename(szPath); } unsigned int _Hash(const char *key) diff --git a/cocos2d-win32.vc2010.sln b/cocos2d-win32.vc2010.sln index 0d2245ee2d..1b4ef4e972 100644 --- a/cocos2d-win32.vc2010.sln +++ b/cocos2d-win32.vc2010.sln @@ -6,6 +6,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libchipmunk", "external\chipmunk\proj.win32\chipmunk.vcxproj", "{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libCocosDenshion", "CocosDenshion\proj.win32\CocosDenshion.vcxproj", "{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}" + ProjectSection(ProjectDependencies) = postProject + {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E} = {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcocos2d", "cocos2dx\proj.win32\cocos2d.vcxproj", "{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}" EndProject diff --git a/cocos2dx/platform/CCFileUtils.h b/cocos2dx/platform/CCFileUtils.h index 9a310d0f53..f37100ed7b 100644 --- a/cocos2dx/platform/CCFileUtils.h +++ b/cocos2dx/platform/CCFileUtils.h @@ -27,18 +27,25 @@ THE SOFTWARE. #include #include "CCPlatformMacros.h" #include "ccTypes.h" +#include "ccTypeInfo.h" NS_CC_BEGIN +class CCDictionary; /** * @addtogroup platform * @{ */ //! @brief Helper class to handle file operations -class CC_DLL CCFileUtils +class CC_DLL CCFileUtils : public TypeInfo { public: + virtual long getClassTypeInfo() { + static const long id = cocos2d::getHashCodeByString(typeid(cocos2d::CCFileUtils).name()); + return id; + } + static CCFileUtils* sharedFileUtils(); static void purgeFileUtils(); @@ -70,8 +77,75 @@ public: If you have not set the ResourcePath, the function appends "/NEWPLUS/TDA_DATA/UserData/" by default. You can set ResourcePath with void setResourcePath(const char *pszResourcePath); */ - const char* fullPathFromRelativePath(const char *pszRelativePath); - + CC_DEPRECATED_ATTRIBUTE const char* fullPathFromRelativePath(const char *pszRelativePath); + + /** Returns the fullpath for a given filename. + + First it will try to get a new filename from the "filenameLookup" dictionary. If a new filename can't be found on the dictionary, it will use the original filename. + Then it will try obtain the full path of the filename using the CCFileUtils search rules: resources directory + + If the filename can't be found on resource directory(e.g. Resources/iphone-hd), it will go back to the root of asset folder(e.g. Resources/) to find the filename. + + If the filename can't be found on the file system, it will return the filename directly. + + This method was added to simplify multiplatform support. Whether you are using cocos2d-js or any cross-compilation toolchain like StellaSDK or Apportable, + you might need to load differerent resources for a given file in the different platforms. + + Examples: + + * In iOS: "image.png" -> "image.pvr" -> "/full/path/res_dir/image.pvr" + * In Android: "image.png" -> "image.png" -> "/full/path/res_dir/image.png" + + @since v2.1 + */ + const char* fullPathForFilename(const char* filename); + + /** + * Loads the filenameLookup dictionary from the contents of a filename. + * + * @note The plist file name should follow the format below: + * + * + * + * + * ios + * + * sounds/click.wav + * sounds/click.caf + * sounds/endgame.wav + * sounds/endgame.caf + * sounds/gem-0.wav + * sounds/gem-0.caf + * + * android + * + * sounds/click.wav + * sounds/click.ogg + * sounds/endgame.wav + * sounds/endgame.ogg + * sounds/gem-0.wav + * sounds/gem-0.ogg + * + * metadata + * + * version + * 1 + * + * + * + * + * @param filename The plist file name. + * + @since v2.1 + */ + void loadFilenameLookupDictionaryFromFile(const char* filename); + + /** Loads the filenameLookup dictionary from the contents of a filename. + + @since v2.1 + */ + void setFilenameLookupDictionary(CCDictionary* pFilenameLookupDict); + /// @cond const char* fullPathFromRelativeFile(const char *pszFilename, const char *pszRelativeFile); /// @endcond @@ -101,10 +175,20 @@ public: protected: CCFileUtils(void) + : m_pFilenameLookupDict(NULL) { } std::string m_obDirectory; + + /** Dictionary used to lookup filenames based on a key. + It is used internally by the following methods: + + const char* fullPathForFilename(const char* )key; + + @since v2.1 + */ + CCDictionary* m_pFilenameLookupDict; }; // end of platform group diff --git a/cocos2dx/platform/CCFileUtilsCommon_cpp.h b/cocos2dx/platform/CCFileUtilsCommon_cpp.h index 7e575eabf6..068b2a8862 100644 --- a/cocos2dx/platform/CCFileUtilsCommon_cpp.h +++ b/cocos2dx/platform/CCFileUtilsCommon_cpp.h @@ -386,6 +386,13 @@ const char* CCFileUtils::getResourceDirectory() return m_obDirectory.c_str(); } +void CCFileUtils::setFilenameLookupDictionary(CCDictionary* pFilenameLookupDict) +{ + CC_SAFE_RELEASE(m_pFilenameLookupDict); + m_pFilenameLookupDict = pFilenameLookupDict; + CC_SAFE_RETAIN(m_pFilenameLookupDict); +} + ////////////////////////////////////////////////////////////////////////// // Notification support when getFileData from invalid file path. ////////////////////////////////////////////////////////////////////////// diff --git a/cocos2dx/platform/android/CCFileUtils.cpp b/cocos2dx/platform/android/CCFileUtils.cpp index cfcd80776b..395d32cfe2 100644 --- a/cocos2dx/platform/android/CCFileUtils.cpp +++ b/cocos2dx/platform/android/CCFileUtils.cpp @@ -66,7 +66,30 @@ void CCFileUtils::purgeCachedEntries() const char* CCFileUtils::fullPathFromRelativePath(const char *pszRelativePath) { - return pszRelativePath; + return fullPathForFilename(pszRelativePath); +} + +static const char* getFilenameForLookupDictionary(CCDictionary* pDict, const char* pszFileName) +{ + const char* pszNewFileName = NULL; + // in Lookup Filename dictionary ? + CCString* fileNameFound = pDict ? (CCString*)pDict->objectForKey(pszFileName) : NULL; + if( NULL == fileNameFound || fileNameFound->length() == 0) { + pszNewFileName = pszFileName; + } + else { + pszNewFileName = fileNameFound->getCString(); + } + return pszNewFileName; +} + +const char* CCFileUtils::fullPathForFilename(const char* pszFileName) +{ + if (pszFileName == NULL || pszFileName[0] == '\0') { + return pszFileName; + } + + return getFilenameForLookupDictionary(m_pFilenameLookupDict, pszFileName); } const char* CCFileUtils::fullPathFromRelativeFile(const char *pszFilename, const char *pszRelativeFile) @@ -75,20 +98,43 @@ const char* CCFileUtils::fullPathFromRelativeFile(const char *pszFilename, const CCString *pRet = new CCString(); pRet->autorelease(); pRet->m_sString = relativeFile.substr(0, relativeFile.rfind('/')+1); - pRet->m_sString += pszFilename; + pRet->m_sString += getFilenameForLookupDictionary(m_pFilenameLookupDict, pszFilename); return pRet->m_sString.c_str(); } +void CCFileUtils::loadFilenameLookupDictionaryFromFile(const char* filename) +{ + const char* pFullPath = this->fullPathForFilename(filename); + if (pFullPath) + { + CCDictionary* pDict = CCDictionary::createWithContentsOfFile(filename); + if (pDict) + { + CCDictionary* pMetadata = (CCDictionary*)pDict->objectForKey("metadata"); + int version = ((CCString*)pMetadata->objectForKey("version"))->intValue(); + if (version != 1) + { + CCLOG("cocos2d: ERROR: Invalid filenameLookup dictionary version: %ld. Filename: %s", (long)version, filename); + return; + } + + setFilenameLookupDictionary((CCDictionary*)pDict->objectForKey("android")); + } + } +} + + unsigned char* CCFileUtils::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize) { unsigned char * pData = 0; - string fullPath(pszFileName); - if ((! pszFileName) || (! pszMode)) + if ((! pszFileName) || (! pszMode) || 0 == strlen(pszFileName)) { return 0; } + string fullPath(pszFileName); + if (pszFileName[0] != '/') { // read from apk diff --git a/cocos2dx/platform/ios/CCFileUtils.mm b/cocos2dx/platform/ios/CCFileUtils.mm index 521575d50e..d28f751a88 100644 --- a/cocos2dx/platform/ios/CCFileUtils.mm +++ b/cocos2dx/platform/ios/CCFileUtils.mm @@ -165,7 +165,7 @@ void CCFileUtils::purgeFileUtils() void CCFileUtils::purgeCachedEntries() { - + CC_SAFE_RELEASE(s_pFileUtils->m_pFilenameLookupDict); } void CCFileUtils::setResourceDirectory(const char *pszDirectoryName) @@ -184,18 +184,39 @@ const char* CCFileUtils::getResourceDirectory() const char* CCFileUtils::fullPathFromRelativePath(const char *pszRelativePath) { - CCAssert(pszRelativePath != NULL, "CCFileUtils: Invalid path"); + return fullPathForFilename(pszRelativePath); +} + +static const char* getFilenameForLookupDictionary(CCDictionary* pDict, const char* pszFileName) +{ + const char* pszNewFileName = NULL; + // in Lookup Filename dictionary ? + CCString* fileNameFound = pDict ? (CCString*)pDict->objectForKey(pszFileName) : NULL; + if( NULL == fileNameFound || fileNameFound->length() == 0) { + pszNewFileName = pszFileName; + } + else { + pszNewFileName = fileNameFound->getCString(); + } + return pszNewFileName; +} + +const char* CCFileUtils::fullPathForFilename(const char* filename) +{ + CCAssert(filename != NULL, "CCFileUtils: Invalid path"); NSString *fullpath = nil; - NSString *relPath = [NSString stringWithUTF8String:pszRelativePath]; + NSString *relPath = [NSString stringWithUTF8String:filename]; // only if it is not an absolute path if( ! [relPath isAbsolutePath] ) { - // pathForResource also searches in .lproj directories. issue #1230 - NSString *lastPathComponent = [relPath lastPathComponent]; + NSString* newfilename = [NSString stringWithUTF8String: getFilenameForLookupDictionary(m_pFilenameLookupDict, filename)]; - NSString *imageDirectory = [relPath stringByDeletingLastPathComponent]; + // pathForResource also searches in .lproj directories. issue #1230 + NSString *lastPathComponent = [newfilename lastPathComponent]; + + NSString *imageDirectory = [newfilename stringByDeletingLastPathComponent]; NSMutableString *imageDirectoryByAppendDirectory = [NSMutableString stringWithUTF8String:m_obDirectory.c_str()]; [imageDirectoryByAppendDirectory appendString:imageDirectory]; @@ -220,13 +241,41 @@ const char* CCFileUtils::fullPathFromRelativePath(const char *pszRelativePath) return [fullpath UTF8String]; } +void CCFileUtils::loadFilenameLookupDictionaryFromFile(const char* filename) +{ + const char* pFullPath = this->fullPathForFilename(filename); + if (pFullPath) + { + CCDictionary* pDict = CCDictionary::createWithContentsOfFile(filename); + if (pDict) + { + CCDictionary* pMetadata = (CCDictionary*)pDict->objectForKey("metadata"); + int version = ((CCString*)pMetadata->objectForKey("version"))->intValue(); + if (version != 1) + { + CCLOG("cocos2d: ERROR: Invalid filenameLookup dictionary version: %ld. Filename: %s", (long)version, filename); + return; + } + + setFilenameLookupDictionary((CCDictionary*)pDict->objectForKey("ios")); + } + } +} + +void CCFileUtils::setFilenameLookupDictionary(CCDictionary* pFilenameLookupDict) +{ + CC_SAFE_RELEASE(m_pFilenameLookupDict); + m_pFilenameLookupDict = pFilenameLookupDict; + CC_SAFE_RETAIN(m_pFilenameLookupDict); +} + const char *CCFileUtils::fullPathFromRelativeFile(const char *pszFilename, const char *pszRelativeFile) { std::string relativeFile = fullPathFromRelativePath(pszRelativeFile); CCString *pRet = new CCString(); pRet->autorelease(); pRet->m_sString = relativeFile.substr(0, relativeFile.rfind('/')+1); - pRet->m_sString += pszFilename; + pRet->m_sString += getFilenameForLookupDictionary(m_pFilenameLookupDict, pszFilename); return pRet->m_sString.c_str(); } diff --git a/cocos2dx/platform/win32/CCFileUtils.cpp b/cocos2dx/platform/win32/CCFileUtils.cpp index d24c880b75..f9dcf1d580 100644 --- a/cocos2dx/platform/win32/CCFileUtils.cpp +++ b/cocos2dx/platform/win32/CCFileUtils.cpp @@ -74,43 +74,64 @@ void CCFileUtils::purgeCachedEntries() } const char* CCFileUtils::fullPathFromRelativePath(const char *pszRelativePath) +{ + return fullPathForFilename(pszRelativePath); +} + +static const char* getFilenameForLookupDictionary(CCDictionary* pDict, const char* pszFileName) +{ + const char* pszNewFileName = NULL; + // in Lookup Filename dictionary ? + CCString* fileNameFound = pDict ? (CCString*)pDict->objectForKey(pszFileName) : NULL; + if( NULL == fileNameFound || fileNameFound->length() == 0) { + pszNewFileName = pszFileName; + } + else { + pszNewFileName = fileNameFound->getCString(); + } + return pszNewFileName; +} + +const char* CCFileUtils::fullPathForFilename(const char* pszFileName) { bool bFileExist = true; const char* resDir = m_obDirectory.c_str(); CCString* pRet = CCString::create(""); + const char* pszNewFileName = getFilenameForLookupDictionary(m_pFilenameLookupDict, pszFileName); + const std::string& resourceRootPath = CCApplication::sharedApplication()->getResourceRootPath(); - if ((strlen(pszRelativePath) > 1 && pszRelativePath[1] == ':')) + if ((strlen(pszNewFileName) > 1 && pszNewFileName[1] == ':')) { // path start with "x:", is absolute path - pRet->m_sString = pszRelativePath; + pRet->m_sString = pszNewFileName; } - else if (strlen(pszRelativePath) > 0 - && ('/' == pszRelativePath[0] || '\\' == pszRelativePath[0])) + else if (strlen(pszNewFileName) > 0 + && ('/' == pszNewFileName[0] || '\\' == pszNewFileName[0])) { // path start with '/' or '\', is absolute path without driver name char szDriver[3] = {s_pszResourcePath[0], s_pszResourcePath[1], 0}; pRet->m_sString = szDriver; - pRet->m_sString += pszRelativePath; + pRet->m_sString += pszNewFileName; } else if (resourceRootPath.length() > 0) { pRet->m_sString = resourceRootPath.c_str(); pRet->m_sString += m_obDirectory.c_str(); - pRet->m_sString += pszRelativePath; + pRet->m_sString += pszNewFileName; } else { pRet->m_sString = s_pszResourcePath; pRet->m_sString += resDir; - pRet->m_sString += pszRelativePath; + pRet->m_sString += pszNewFileName; } // If file or directory doesn't exist, try to find it in the root path. if (GetFileAttributesA(pRet->m_sString.c_str()) == -1) { pRet->m_sString = s_pszResourcePath; - pRet->m_sString += pszRelativePath; + pRet->m_sString += pszNewFileName; if (GetFileAttributesA(pRet->m_sString.c_str()) == -1) { @@ -120,19 +141,40 @@ const char* CCFileUtils::fullPathFromRelativePath(const char *pszRelativePath) if (!bFileExist) { // Can't find the file, return the relative path. - pRet->m_sString = pszRelativePath; + pRet->m_sString = pszNewFileName; } return pRet->m_sString.c_str(); } +void CCFileUtils::loadFilenameLookupDictionaryFromFile(const char* filename) +{ + const char* pFullPath = this->fullPathForFilename(filename); + if (pFullPath) + { + CCDictionary* pDict = CCDictionary::createWithContentsOfFile(filename); + if (pDict) + { + CCDictionary* pMetadata = (CCDictionary*)pDict->objectForKey("metadata"); + int version = ((CCString*)pMetadata->objectForKey("version"))->intValue(); + if (version != 1) + { + CCLOG("cocos2d: ERROR: Invalid filenameLookup dictionary version: %ld. Filename: %s", (long)version, filename); + return; + } + + setFilenameLookupDictionary((CCDictionary*)pDict->objectForKey("win32")); + } + } +} + const char *CCFileUtils::fullPathFromRelativeFile(const char *pszFilename, const char *pszRelativeFile) { - // std::string relativeFile = fullPathFromRelativePath(pszRelativeFile); + //std::string relativeFile = fullPathFromRelativePath(pszRelativeFile); std::string relativeFile = pszRelativeFile; CCString *pRet = CCString::create(""); pRet->m_sString = relativeFile.substr(0, relativeFile.find_last_of("/\\") + 1); - pRet->m_sString += pszFilename; + pRet->m_sString += getFilenameForLookupDictionary(m_pFilenameLookupDict, pszFilename); return pRet->m_sString.c_str(); } diff --git a/cocos2dx/sprite_nodes/CCSpriteFrameCache.cpp b/cocos2dx/sprite_nodes/CCSpriteFrameCache.cpp index 2d9881ca3c..5bbd348b19 100644 --- a/cocos2dx/sprite_nodes/CCSpriteFrameCache.cpp +++ b/cocos2dx/sprite_nodes/CCSpriteFrameCache.cpp @@ -246,13 +246,13 @@ void CCSpriteFrameCache::addSpriteFramesWithFile(const char *pszPlist) if (! texturePath.empty()) { - // build texture path relative to plist file - texturePath = CCFileUtils::sharedFileUtils()->fullPathFromRelativeFile(texturePath.c_str(), pszPath); + // build texture path relative to plist file + texturePath = CCFileUtils::sharedFileUtils()->fullPathFromRelativeFile(texturePath.c_str(), pszPlist); } else { // build texture path by replacing file extension - texturePath = pszPath; + texturePath = pszPlist; // remove .xxx size_t startPos = texturePath.find_last_of("."); diff --git a/cocos2dx/textures/CCTextureCache.cpp b/cocos2dx/textures/CCTextureCache.cpp index 764ec9b1f0..c4a35586ba 100644 --- a/cocos2dx/textures/CCTextureCache.cpp +++ b/cocos2dx/textures/CCTextureCache.cpp @@ -407,7 +407,7 @@ CCTexture2D * CCTextureCache::addImage(const char * path) std::string fullpath = pathKey; // (CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(path)); if( ! texture ) { - std::string lowerCase(path); + std::string lowerCase(pathKey); for (unsigned int i = 0; i < lowerCase.length(); ++i) { lowerCase[i] = tolower(lowerCase[i]); diff --git a/samples/Javascript/CrystalCraze/Classes/AppDelegate.cpp b/samples/Javascript/CrystalCraze/Classes/AppDelegate.cpp index b975e1f8e8..5862c19576 100644 --- a/samples/Javascript/CrystalCraze/Classes/AppDelegate.cpp +++ b/samples/Javascript/CrystalCraze/Classes/AppDelegate.cpp @@ -34,17 +34,18 @@ bool AppDelegate::applicationDidFinishLaunching() CCSize designSize = CCSizeMake(320, 480); CCSize resourceSize = CCSizeMake(320, 480); - if (screenSize.height > 1024) - { - resourceSize = CCSizeMake(1536, 2048); - CCFileUtils::sharedFileUtils()->setResourceDirectory("resources-ipadhd"); - } - else if (screenSize.height > 960) - { - resourceSize = CCSizeMake(768, 1536); - CCFileUtils::sharedFileUtils()->setResourceDirectory("resources-ipad"); - } - else if (screenSize.height > 480) +// if (screenSize.height > 1024) +// { +// resourceSize = CCSizeMake(1536, 2048); +// CCFileUtils::sharedFileUtils()->setResourceDirectory("resources-ipadhd"); +// } +// else if (screenSize.height > 960) +// { +// resourceSize = CCSizeMake(768, 1536); +// CCFileUtils::sharedFileUtils()->setResourceDirectory("resources-ipad"); +// } +// else + if (screenSize.height > 480) { resourceSize = CCSizeMake(640, 960); CCFileUtils::sharedFileUtils()->setResourceDirectory("resources-iphonehd"); @@ -57,7 +58,7 @@ bool AppDelegate::applicationDidFinishLaunching() pDirector->setContentScaleFactor(resourceSize.height/designSize.height); - CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionNoBorder); + CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionShowAll); // turn on display FPS pDirector->setDisplayStats(true); diff --git a/samples/Javascript/CrystalCraze/proj.android/build_native.sh b/samples/Javascript/CrystalCraze/proj.android/build_native.sh index 3b8eb8d36a..d1174110c6 100755 --- a/samples/Javascript/CrystalCraze/proj.android/build_native.sh +++ b/samples/Javascript/CrystalCraze/proj.android/build_native.sh @@ -49,7 +49,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" COCOS2DX_ROOT="$DIR/../../../.." APP_ROOT="$DIR/.." APP_ANDROID_ROOT="$DIR" -RESROUCE_ROOT="$APP_ROOT/../Shared/games/CrystalCraze/Published-iOS" +RESROUCE_ROOT="$APP_ROOT/../Shared/games/CrystalCraze/Published-Cocos2d-x" BINDINGS_JS_ROOT="$APP_ROOT/../../../scripting/javascript/bindings/js" echo @@ -76,6 +76,12 @@ cp -rf "$RESROUCE_ROOT"/* "$APP_ANDROID_ROOT"/assets # copy bindings/*.js into assets' root cp -f "$BINDINGS_JS_ROOT"/*.js "$APP_ANDROID_ROOT"/assets +# remove test_image_rgba4444.pvr.gz +rm -f "$APP_ANDROID_ROOT"/assets/resources-iphone/*.pvr.gz +rm -f "$APP_ANDROID_ROOT"/assets/resources-iphonehd/*.pvr.gz +rm -f "$APP_ANDROID_ROOT"/assets/resources-iphone/gamescene/*.pvr.gz +rm -f "$APP_ANDROID_ROOT"/assets/resources-iphonehd/gamescene/*.pvr.gz + echo "Using prebuilt externals" echo diff --git a/samples/Javascript/CrystalCraze/proj.ios/CrystalCraze.xcodeproj/project.pbxproj.REMOVED.git-id b/samples/Javascript/CrystalCraze/proj.ios/CrystalCraze.xcodeproj/project.pbxproj.REMOVED.git-id index a66ff5648c..dc669c4a89 100644 --- a/samples/Javascript/CrystalCraze/proj.ios/CrystalCraze.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/samples/Javascript/CrystalCraze/proj.ios/CrystalCraze.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -745aa683d87ef9e600ad3592f86adeb2bb981bf8 \ No newline at end of file +536303877833596433c1e0a8337600dc52a88013 \ No newline at end of file diff --git a/samples/Javascript/CrystalCraze/proj.win32/CrystalCraze.vcxproj b/samples/Javascript/CrystalCraze/proj.win32/CrystalCraze.vcxproj index 25705c394e..c4ee52150d 100644 --- a/samples/Javascript/CrystalCraze/proj.win32/CrystalCraze.vcxproj +++ b/samples/Javascript/CrystalCraze/proj.win32/CrystalCraze.vcxproj @@ -108,7 +108,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\..\scripting\javascript\spidermonkey-win32\li if exist "$(OutDir)\CrystalCrazeRes" rd /s /q "$(OutDir)\CrystalCrazeRes" mkdir "$(OutDir)\CrystalCrazeRes" xcopy "$(ProjectDir)..\..\..\..\scripting\javascript\bindings\js\*.js" "$(OutDir)\CrystalCrazeRes" /e /Y -xcopy "$(ProjectDir)..\..\Shared\games\CrystalCraze\Published-iOS" "$(OutDir)\CrystalCrazeRes\" /e /Y +xcopy "$(ProjectDir)..\..\Shared\games\CrystalCraze\Published-Cocos2d-x" "$(OutDir)\CrystalCrazeRes\" /e /Y Copy js and resource files. @@ -161,7 +161,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\..\scripting\javascript\spidermonkey-win32\li if exist "$(OutDir)\CrystalCrazeRes" rd /s /q "$(OutDir)\CrystalCrazeRes" mkdir "$(OutDir)\CrystalCrazeRes" xcopy "$(ProjectDir)..\..\..\..\scripting\javascript\bindings\js\*.js" "$(OutDir)\CrystalCrazeRes" /e /Y -xcopy "$(ProjectDir)..\..\Shared\games\CrystalCraze\Published-iOS" "$(OutDir)\CrystalCrazeRes\" /e /Y +xcopy "$(ProjectDir)..\..\Shared\games\CrystalCraze\Published-Cocos2d-x" "$(OutDir)\CrystalCrazeRes\" /e /Y Copy js and resource files. diff --git a/samples/Javascript/Shared b/samples/Javascript/Shared index 76f9185e8c..da6020e5c5 160000 --- a/samples/Javascript/Shared +++ b/samples/Javascript/Shared @@ -1 +1 @@ -Subproject commit 76f9185e8cf78ea92554892c0fe6bea98491122e +Subproject commit da6020e5c5528b4bf6b1f27d53f76947ca1993ce diff --git a/tools/tojs/cocos2dx-win32.ini b/tools/tojs/cocos2dx-win32.ini index a5b957cc8f..487d4a4def 100644 --- a/tools/tojs/cocos2dx-win32.ini +++ b/tools/tojs/cocos2dx-win32.ini @@ -117,7 +117,8 @@ rename_functions = CCDirector::[sharedDirector=getInstance], CCCamera.*::[setUpXYZ=setUp getUpXYZ=getUp setEyeXYZ=setEye getEyeXYZ=getEye setCenterXYZ=setCenter getCenterXYZ=getCenter], CCBReader::[getAnimationManager=getActionManager setAnimationManager=setActionManager], CCTMXTiledMap::[layerNamed=getLayer objectGroupNamed=getObjectGroup propertyNamed=getProperty], - CCTexture2D::[defaultAlphaPixelFormat=getDefaultAlphaPixelFormat] + CCTexture2D::[defaultAlphaPixelFormat=getDefaultAlphaPixelFormat], + CCFileUtils::[sharedFileUtils=getInstance loadFilenameLookupDictionaryFromFile=loadFilenameLookup] rename_classes = CCParticleSystemQuad::CCParticleSystem, SimpleAudioEngine::AudioEngine, @@ -128,8 +129,8 @@ rename_classes = CCParticleSystemQuad::CCParticleSystem, remove_prefix = CC # objects for which there will be no "parent" lookup -base_objects = CCNode CCDirector SimpleAudioEngine +base_objects = CCNode CCDirector SimpleAudioEngine CCFileUtils # classes that create no constructor # CCSet is special and we will use a hand-written constructor -abstract_classes = CCDirector CCSpriteFrameCache CCTransitionEaseScene CCSet SimpleAudioEngine +abstract_classes = CCDirector CCSpriteFrameCache CCTransitionEaseScene CCSet SimpleAudioEngine CCFileUtils diff --git a/tools/tojs/cocos2dx.ini b/tools/tojs/cocos2dx.ini index e77ce94ac8..40e0bc3459 100644 --- a/tools/tojs/cocos2dx.ini +++ b/tools/tojs/cocos2dx.ini @@ -26,7 +26,7 @@ headers = %(cocosdir)s/cocos2dx/include/cocos2d.h %(cocosdir)s/CocosDenshion/inc # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^CCMenu*$". -classes = CCSprite.* CCScene CCNode CCDirector CCLayer.* CCMenu.* CCTouch CC.*Action.* CCMove.* CCRotate.* CCBlink.* CCTint.* CCSequence CCRepeat.* CCFade.* CCEase.* CCScale.* CCTransition.* CCSpawn CCSequence CCAnimat.* CCFlip.* CCDelay.* CCSkew.* CCJump.* CCPlace.* CCShow.* CCProgress.* CCPointArray CCToggleVisibility.* CCHide CCParticle.* CCLabel.* CCAtlas.* CCTextureCache.* CCTexture2D CCCardinal.* CCCatmullRom.* CCParallaxNode CCTileMap.* CCTMX.* CCCallFunc CCRenderTexture CCGridAction CCGrid3DAction CCShaky3D CCWaves3D CCFlipX3D CCFlipY3D CCSpeed CCActionManager CCBReader.* CCBAnimationManager.* CCSet SimpleAudioEngine CCScheduler CCTimer CCOrbit.* CCFollow.* CCBezier.* CCCardinalSpline.* CCControlButton.* CCCamera.* CCDrawNode CC.*3D$ CCLiquid$ CCWaves$ CCShuffleTiles$ CCTurnOffTiles$ CCSplit.* CCTwirl$ +classes = CCSprite.* CCScene CCNode CCDirector CCLayer.* CCMenu.* CCTouch CC.*Action.* CCMove.* CCRotate.* CCBlink.* CCTint.* CCSequence CCRepeat.* CCFade.* CCEase.* CCScale.* CCTransition.* CCSpawn CCSequence CCAnimat.* CCFlip.* CCDelay.* CCSkew.* CCJump.* CCPlace.* CCShow.* CCProgress.* CCPointArray CCToggleVisibility.* CCHide CCParticle.* CCLabel.* CCAtlas.* CCTextureCache.* CCTexture2D CCCardinal.* CCCatmullRom.* CCParallaxNode CCTileMap.* CCTMX.* CCCallFunc CCRenderTexture CCGridAction CCGrid3DAction CCShaky3D CCWaves3D CCFlipX3D CCFlipY3D CCSpeed CCActionManager CCBReader.* CCBAnimationManager.* CCSet SimpleAudioEngine CCScheduler CCTimer CCOrbit.* CCFollow.* CCBezier.* CCCardinalSpline.* CCControlButton.* CCCamera.* CCDrawNode CC.*3D$ CCLiquid$ CCWaves$ CCShuffleTiles$ CCTurnOffTiles$ CCSplit.* CCTwirl$ CCFileUtils$ # what should we skip? in the format ClassName::[function function] # ClassName is a regular expression, but will be used like this: "^ClassName$" functions are also @@ -120,7 +120,8 @@ rename_functions = CCDirector::[sharedDirector=getInstance], CCCamera.*::[setUpXYZ=setUp getUpXYZ=getUp setEyeXYZ=setEye getEyeXYZ=getEye setCenterXYZ=setCenter getCenterXYZ=getCenter], CCBReader::[getAnimationManager=getActionManager setAnimationManager=setActionManager], CCTMXTiledMap::[layerNamed=getLayer objectGroupNamed=getObjectGroup propertyNamed=getProperty], - CCTexture2D::[defaultAlphaPixelFormat=getDefaultAlphaPixelFormat] + CCTexture2D::[defaultAlphaPixelFormat=getDefaultAlphaPixelFormat], + CCFileUtils::[sharedFileUtils=getInstance loadFilenameLookupDictionaryFromFile=loadFilenameLookup] rename_classes = CCParticleSystemQuad::CCParticleSystem, SimpleAudioEngine::AudioEngine, @@ -131,8 +132,8 @@ rename_classes = CCParticleSystemQuad::CCParticleSystem, remove_prefix = CC # objects for which there will be no "parent" lookup -base_objects = CCNode CCDirector SimpleAudioEngine +base_objects = CCNode CCDirector SimpleAudioEngine CCFileUtils # classes that create no constructor # CCSet is special and we will use a hand-written constructor -abstract_classes = CCDirector CCSpriteFrameCache CCTransitionEaseScene CCSet SimpleAudioEngine +abstract_classes = CCDirector CCSpriteFrameCache CCTransitionEaseScene CCSet SimpleAudioEngine CCFileUtils