mirror of https://github.com/axmolengine/axmol.git
Merge branch 'v3_testMerge' of https://github.com/pandamicro/cocos2d-x into v3_assetsmanager
Conflicts: build/cocos2d_libs.xcodeproj/project.pbxproj cocos/platform/CCFileUtils.cpp tests/lua-tests/project/CMakeLists.txt tests/lua-tests/project/Classes/AppDelegate.cpp tests/lua-tests/project/proj.android/jni/Android.mk tests/lua-tests/project/proj.win32/lua-tests.win32.vcxproj
This commit is contained in:
commit
064e159c70
|
@ -700,8 +700,8 @@
|
|||
1AC35D7A18CEE59900F37B72 /* cocosbuilderRes in Resources */ = {isa = PBXBuildFile; fileRef = 1AC35D7818CEE59900F37B72 /* cocosbuilderRes */; };
|
||||
1AC35D8118CEE5B100F37B72 /* AppDelegate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC35D7D18CEE5B100F37B72 /* AppDelegate.cpp */; };
|
||||
1AC35D8218CEE5B100F37B72 /* AppDelegate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC35D7D18CEE5B100F37B72 /* AppDelegate.cpp */; };
|
||||
1AC35D8318CEE5B100F37B72 /* lua_assetsmanager_test_sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC35D7F18CEE5B100F37B72 /* lua_assetsmanager_test_sample.cpp */; };
|
||||
1AC35D8418CEE5B100F37B72 /* lua_assetsmanager_test_sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC35D7F18CEE5B100F37B72 /* lua_assetsmanager_test_sample.cpp */; };
|
||||
1AC35D8318CEE5B100F37B72 /* lua_assetsmanagerex_test_sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC35D7F18CEE5B100F37B72 /* lua_assetsmanagerex_test_sample.cpp */; };
|
||||
1AC35D8418CEE5B100F37B72 /* lua_assetsmanagerex_test_sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC35D7F18CEE5B100F37B72 /* lua_assetsmanagerex_test_sample.cpp */; };
|
||||
1AC35D9818CEE5D100F37B72 /* AppController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AC35D8718CEE5D100F37B72 /* AppController.mm */; };
|
||||
1AC35D9918CEE5D100F37B72 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1AC35D8818CEE5D100F37B72 /* Default-568h@2x.png */; };
|
||||
1AC35D9A18CEE5D100F37B72 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 1AC35D8918CEE5D100F37B72 /* Default.png */; };
|
||||
|
@ -957,6 +957,12 @@
|
|||
B609E67419C18DAD003D0074 /* BillBoardTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B609E67119C18DAD003D0074 /* BillBoardTest.cpp */; };
|
||||
B6C039D919C95D83007207DC /* LightTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6C039D719C95D83007207DC /* LightTest.cpp */; };
|
||||
B6C039DA19C95D83007207DC /* LightTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6C039D719C95D83007207DC /* LightTest.cpp */; };
|
||||
BA4B67D219E6699200BAF8F9 /* AssetsManagerExTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BA4B67D019E6699200BAF8F9 /* AssetsManagerExTest.cpp */; };
|
||||
BA4B67D319E6699200BAF8F9 /* AssetsManagerExTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BA4B67D019E6699200BAF8F9 /* AssetsManagerExTest.cpp */; };
|
||||
BAF402E219E675F30060A895 /* Manifests in Resources */ = {isa = PBXBuildFile; fileRef = BAF402E119E675F30060A895 /* Manifests */; };
|
||||
BAF402E319E675F30060A895 /* Manifests in Resources */ = {isa = PBXBuildFile; fileRef = BAF402E119E675F30060A895 /* Manifests */; };
|
||||
BAF402E419E676370060A895 /* Manifests in Resources */ = {isa = PBXBuildFile; fileRef = BAF402E119E675F30060A895 /* Manifests */; };
|
||||
BAF402E519E6764A0060A895 /* Manifests in Resources */ = {isa = PBXBuildFile; fileRef = BAF402E119E675F30060A895 /* Manifests */; };
|
||||
C04F935A1941B05400E9FEAB /* TileMapTest2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C04F93581941B05400E9FEAB /* TileMapTest2.cpp */; };
|
||||
C04F935B1941B05400E9FEAB /* TileMapTest2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C04F93581941B05400E9FEAB /* TileMapTest2.cpp */; };
|
||||
C08689C118D370C90093E810 /* background.caf in Resources */ = {isa = PBXBuildFile; fileRef = C08689C018D370C90093E810 /* background.caf */; };
|
||||
|
@ -2782,8 +2788,8 @@
|
|||
1AC35D7818CEE59900F37B72 /* cocosbuilderRes */ = {isa = PBXFileReference; lastKnownFileType = folder; name = cocosbuilderRes; path = "../tests/lua-tests/res/cocosbuilderRes"; sourceTree = "<group>"; };
|
||||
1AC35D7D18CEE5B100F37B72 /* AppDelegate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppDelegate.cpp; sourceTree = "<group>"; };
|
||||
1AC35D7E18CEE5B100F37B72 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
1AC35D7F18CEE5B100F37B72 /* lua_assetsmanager_test_sample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lua_assetsmanager_test_sample.cpp; sourceTree = "<group>"; };
|
||||
1AC35D8018CEE5B100F37B72 /* lua_assetsmanager_test_sample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lua_assetsmanager_test_sample.h; sourceTree = "<group>"; };
|
||||
1AC35D7F18CEE5B100F37B72 /* lua_assetsmanagerex_test_sample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lua_assetsmanagerex_test_sample.cpp; sourceTree = "<group>"; };
|
||||
1AC35D8018CEE5B100F37B72 /* lua_assetsmanagerex_test_sample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lua_assetsmanagerex_test_sample.h; sourceTree = "<group>"; };
|
||||
1AC35D8618CEE5D100F37B72 /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppController.h; sourceTree = "<group>"; };
|
||||
1AC35D8718CEE5D100F37B72 /* AppController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppController.mm; sourceTree = "<group>"; };
|
||||
1AC35D8818CEE5D100F37B72 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
|
||||
|
@ -2986,6 +2992,9 @@
|
|||
B609E67219C18DAD003D0074 /* BillBoardTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BillBoardTest.h; path = BillBoardTest/BillBoardTest.h; sourceTree = "<group>"; };
|
||||
B6C039D719C95D83007207DC /* LightTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LightTest.cpp; path = LightTest/LightTest.cpp; sourceTree = "<group>"; };
|
||||
B6C039D819C95D83007207DC /* LightTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LightTest.h; path = LightTest/LightTest.h; sourceTree = "<group>"; };
|
||||
BA4B67D019E6699200BAF8F9 /* AssetsManagerExTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AssetsManagerExTest.cpp; sourceTree = "<group>"; };
|
||||
BA4B67D119E6699200BAF8F9 /* AssetsManagerExTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssetsManagerExTest.h; sourceTree = "<group>"; };
|
||||
BAF402E119E675F30060A895 /* Manifests */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Manifests; path = "../tests/cpp-tests/Resources/Manifests"; sourceTree = "<group>"; };
|
||||
C04F93581941B05400E9FEAB /* TileMapTest2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TileMapTest2.cpp; sourceTree = "<group>"; };
|
||||
C04F93591941B05400E9FEAB /* TileMapTest2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TileMapTest2.h; sourceTree = "<group>"; };
|
||||
C08689C018D370C90093E810 /* background.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = background.caf; path = "../tests/cpp-tests/Resources/background.caf"; sourceTree = "<group>"; };
|
||||
|
@ -5805,6 +5814,7 @@
|
|||
1AC359B418CECF0B00F37B72 /* ExtensionsTest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BA4B67CF19E6699200BAF8F9 /* AssetsManagerExTest */,
|
||||
38FA2E70194AEBE100FF2BE4 /* CocoStudioActionTimelineTest */,
|
||||
1AC359B518CECF0B00F37B72 /* CocosBuilderTest */,
|
||||
1AC359DC18CECF0B00F37B72 /* CocoStudioArmatureTest */,
|
||||
|
@ -6502,6 +6512,7 @@
|
|||
1AC35CBA18CED84500F37B72 /* fonts */,
|
||||
1AC35CBC18CED84500F37B72 /* hd */,
|
||||
1AC35CBE18CED84500F37B72 /* Images */,
|
||||
BAF402E119E675F30060A895 /* Manifests */,
|
||||
1AC35CC118CED84500F37B72 /* Misc */,
|
||||
1AC35CC318CED84500F37B72 /* Particles */,
|
||||
1AC35CC618CED84500F37B72 /* Shaders */,
|
||||
|
@ -6631,8 +6642,8 @@
|
|||
15427B76198B750300DC375D /* lua_module_register.h */,
|
||||
1AC35D7D18CEE5B100F37B72 /* AppDelegate.cpp */,
|
||||
1AC35D7E18CEE5B100F37B72 /* AppDelegate.h */,
|
||||
1AC35D7F18CEE5B100F37B72 /* lua_assetsmanager_test_sample.cpp */,
|
||||
1AC35D8018CEE5B100F37B72 /* lua_assetsmanager_test_sample.h */,
|
||||
1AC35D7F18CEE5B100F37B72 /* lua_assetsmanagerex_test_sample.cpp */,
|
||||
1AC35D8018CEE5B100F37B72 /* lua_assetsmanagerex_test_sample.h */,
|
||||
);
|
||||
name = Classes;
|
||||
path = "../tests/lua-tests/project/Classes";
|
||||
|
@ -7207,6 +7218,15 @@
|
|||
name = LightTest;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BA4B67CF19E6699200BAF8F9 /* AssetsManagerExTest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BA4B67D019E6699200BAF8F9 /* AssetsManagerExTest.cpp */,
|
||||
BA4B67D119E6699200BAF8F9 /* AssetsManagerExTest.h */,
|
||||
);
|
||||
path = AssetsManagerExTest;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
|
@ -7654,6 +7674,7 @@
|
|||
15D1FCF11998637C00302043 /* Cocos2d.lua in Resources */,
|
||||
3E2F27BC19D00D7200E7C490 /* audio in Resources */,
|
||||
1AC35DC318CEE65100F37B72 /* Misc in Resources */,
|
||||
BAF402E419E676370060A895 /* Manifests in Resources */,
|
||||
1AC35DC618CEE65100F37B72 /* Shaders in Resources */,
|
||||
1529F05C19ED88830064B9B1 /* tp.lua in Resources */,
|
||||
15D1FD141998637C00302043 /* extern.lua in Resources */,
|
||||
|
@ -7739,6 +7760,7 @@
|
|||
15D1FD111998637C00302043 /* DrawPrimitives.lua in Resources */,
|
||||
15D1FD1B1998637C00302043 /* json.lua in Resources */,
|
||||
1AC35DD618CEE65200F37B72 /* Misc in Resources */,
|
||||
BAF402E519E6764A0060A895 /* Manifests in Resources */,
|
||||
15D1FD3E199863CA00302043 /* DeprecatedCocosDenshionClass.lua in Resources */,
|
||||
1AC35DF718CEE65B00F37B72 /* effect1.wav in Resources */,
|
||||
C08689C418D370C90093E810 /* background.caf in Resources */,
|
||||
|
@ -7835,6 +7857,7 @@
|
|||
1AC35CFA18CED84500F37B72 /* Misc in Resources */,
|
||||
38FA2E76194AECF800FF2BE4 /* ActionTimeline in Resources */,
|
||||
1AC35D0418CED84500F37B72 /* Shaders in Resources */,
|
||||
BAF402E219E675F30060A895 /* Manifests in Resources */,
|
||||
3E2F27BA19CFF52300E7C490 /* audio in Resources */,
|
||||
1AC35CD818CED84500F37B72 /* CocosBuilderExample.ccbresourcelog in Resources */,
|
||||
B2507B6B192589AF00FA4972 /* Shaders3D in Resources */,
|
||||
|
@ -7914,6 +7937,7 @@
|
|||
3E2BDAD219BEA3E20055CDCD /* audio in Resources */,
|
||||
C08689C318D370C90093E810 /* background.caf in Resources */,
|
||||
1AC35C9518CECF1400F37B72 /* Icon-72.png in Resources */,
|
||||
BAF402E319E675F30060A895 /* Manifests in Resources */,
|
||||
1AC35D0B18CED84500F37B72 /* zwoptex in Resources */,
|
||||
1AC35CF518CED84500F37B72 /* Images in Resources */,
|
||||
1AC35C9118CECF1400F37B72 /* Icon-40.png in Resources */,
|
||||
|
@ -8030,7 +8054,7 @@
|
|||
1AC35DB518CEE5DA00F37B72 /* LuaObjectCBridgeTest.mm in Sources */,
|
||||
150F918819DA409E00B89F57 /* lua_test_bindings.cpp in Sources */,
|
||||
1AC35DB618CEE5DA00F37B72 /* main.cpp in Sources */,
|
||||
1AC35D8318CEE5B100F37B72 /* lua_assetsmanager_test_sample.cpp in Sources */,
|
||||
1AC35D8318CEE5B100F37B72 /* lua_assetsmanagerex_test_sample.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -8044,7 +8068,7 @@
|
|||
1AC35D9818CEE5D100F37B72 /* AppController.mm in Sources */,
|
||||
1AC35D8218CEE5B100F37B72 /* AppDelegate.cpp in Sources */,
|
||||
1AC35DA618CEE5D100F37B72 /* RootViewController.mm in Sources */,
|
||||
1AC35D8418CEE5B100F37B72 /* lua_assetsmanager_test_sample.cpp in Sources */,
|
||||
1AC35D8418CEE5B100F37B72 /* lua_assetsmanagerex_test_sample.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -8209,6 +8233,7 @@
|
|||
1AC35C4B18CECF0C00F37B72 /* ShaderTest2.cpp in Sources */,
|
||||
38FA2E73194AEBE100FF2BE4 /* ActionTimelineTestScene.cpp in Sources */,
|
||||
1AC35C6518CECF0C00F37B72 /* UnitTest.cpp in Sources */,
|
||||
BA4B67D219E6699200BAF8F9 /* AssetsManagerExTest.cpp in Sources */,
|
||||
29080DC9191B595E0066F8DF /* UISceneManager_Editor.cpp in Sources */,
|
||||
1AC35B3F18CECF0C00F37B72 /* Bug-458.cpp in Sources */,
|
||||
3E2F27B919CFF4AF00E7C490 /* NewAudioEngineTest.cpp in Sources */,
|
||||
|
@ -8353,6 +8378,7 @@
|
|||
1AC35B7C18CECF0C00F37B72 /* GameOverScene.cpp in Sources */,
|
||||
1AC35BF418CECF0C00F37B72 /* ExtensionsTest.cpp in Sources */,
|
||||
1AC35B3618CECF0C00F37B72 /* TestEntries.cpp in Sources */,
|
||||
BA4B67D319E6699200BAF8F9 /* AssetsManagerExTest.cpp in Sources */,
|
||||
1AC35B2E18CECF0C00F37B72 /* Box2dTest.cpp in Sources */,
|
||||
29080DCA191B595E0066F8DF /* UISceneManager_Editor.cpp in Sources */,
|
||||
1AC35C1218CECF0C00F37B72 /* LabelTestNew.cpp in Sources */,
|
||||
|
|
|
@ -184,6 +184,11 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.*
|
|||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\extensions\assets-manager\AssetsManager.cpp" />
|
||||
<ClCompile Include="..\..\extensions\assets-manager\AssetsManagerEx.cpp" />
|
||||
<ClCompile Include="..\..\extensions\assets-manager\CCEventAssetsManagerEx.cpp" />
|
||||
<ClCompile Include="..\..\extensions\assets-manager\CCEventListenerAssetsManagerEx.cpp" />
|
||||
<ClCompile Include="..\..\extensions\assets-manager\Downloader.cpp" />
|
||||
<ClCompile Include="..\..\extensions\assets-manager\Manifest.cpp" />
|
||||
<ClCompile Include="..\..\extensions\GUI\CCControlExtension\CCControl.cpp" />
|
||||
<ClCompile Include="..\..\extensions\GUI\CCControlExtension\CCControlButton.cpp" />
|
||||
<ClCompile Include="..\..\extensions\GUI\CCControlExtension\CCControlColourPicker.cpp" />
|
||||
|
@ -529,6 +534,11 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.*
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\extensions\assets-manager\AssetsManager.h" />
|
||||
<ClInclude Include="..\..\extensions\assets-manager\AssetsManagerEx.h" />
|
||||
<ClInclude Include="..\..\extensions\assets-manager\CCEventAssetsManagerEx.h" />
|
||||
<ClInclude Include="..\..\extensions\assets-manager\CCEventListenerAssetsManagerEx.h" />
|
||||
<ClInclude Include="..\..\extensions\assets-manager\Downloader.h" />
|
||||
<ClInclude Include="..\..\extensions\assets-manager\Manifest.h" />
|
||||
<ClInclude Include="..\..\extensions\cocos-ext.h" />
|
||||
<ClInclude Include="..\..\extensions\ExtensionExport.h" />
|
||||
<ClInclude Include="..\..\extensions\ExtensionMacros.h" />
|
||||
|
|
|
@ -1177,6 +1177,21 @@
|
|||
<ClCompile Include="..\ui\UIEditBox\UIEditBoxImpl-win32.cpp">
|
||||
<Filter>ui\UIWidgets\EditBox</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\extensions\assets-manager\AssetsManagerEx.cpp">
|
||||
<Filter>extension\AssetsManager</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\extensions\assets-manager\CCEventAssetsManagerEx.cpp">
|
||||
<Filter>extension\AssetsManager</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\extensions\assets-manager\CCEventListenerAssetsManagerEx.cpp">
|
||||
<Filter>extension\AssetsManager</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\extensions\assets-manager\Downloader.cpp">
|
||||
<Filter>extension\AssetsManager</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\extensions\assets-manager\Manifest.cpp">
|
||||
<Filter>extension\AssetsManager</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\ui\UIWebViewImpl-win32.cpp">
|
||||
<Filter>ui\UIWidgets</Filter>
|
||||
</ClCompile>
|
||||
|
@ -2375,6 +2390,21 @@
|
|||
<ClInclude Include="..\ui\UIEditBox\UIEditBoxImpl-win32.h">
|
||||
<Filter>ui\UIWidgets\EditBox</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\extensions\assets-manager\AssetsManagerEx.h">
|
||||
<Filter>extension\AssetsManager</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\extensions\assets-manager\CCEventAssetsManagerEx.h">
|
||||
<Filter>extension\AssetsManager</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\extensions\assets-manager\CCEventListenerAssetsManagerEx.h">
|
||||
<Filter>extension\AssetsManager</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\extensions\assets-manager\Downloader.h">
|
||||
<Filter>extension\AssetsManager</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\extensions\assets-manager\Manifest.h">
|
||||
<Filter>extension\AssetsManager</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ui\UIWebViewImpl-win32.h">
|
||||
<Filter>ui\UIWidgets</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -195,7 +195,8 @@ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) \
|
|||
$(LOCAL_PATH)/../external/unzip \
|
||||
$(LOCAL_PATH)/../external/chipmunk/include/chipmunk \
|
||||
$(LOCAL_PATH)/../external/xxhash \
|
||||
$(LOCAL_PATH)/../external/nslog
|
||||
$(LOCAL_PATH)/../external/nslog \
|
||||
$(LOCAL_PATH)/base
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH) \
|
||||
$(LOCAL_PATH)/. \
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010-2013 cocos2d-x.org
|
||||
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
Copyright (c) 2010-2013 cocos2d-x.org
|
||||
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#ifndef __CC_FILEUTILS_H__
|
||||
#define __CC_FILEUTILS_H__
|
||||
|
||||
|
@ -49,18 +49,18 @@ public:
|
|||
* Gets the instance of FileUtils.
|
||||
*/
|
||||
static FileUtils* getInstance();
|
||||
|
||||
|
||||
/**
|
||||
* Destroys the instance of FileUtils.
|
||||
*/
|
||||
static void destroyInstance();
|
||||
|
||||
|
||||
/** @deprecated Use getInstance() instead */
|
||||
CC_DEPRECATED_ATTRIBUTE static FileUtils* sharedFileUtils() { return getInstance(); }
|
||||
|
||||
|
||||
/** @deprecated Use destroyInstance() instead */
|
||||
CC_DEPRECATED_ATTRIBUTE static void purgeFileUtils() { destroyInstance(); }
|
||||
|
||||
|
||||
/**
|
||||
* The destructor of FileUtils.
|
||||
* @js NA
|
||||
|
@ -99,7 +99,7 @@ public:
|
|||
* @warning Recall: you are responsible for calling free() on any Non-NULL pointer returned.
|
||||
*/
|
||||
CC_DEPRECATED_ATTRIBUTE virtual unsigned char* getFileData(const std::string& filename, const char* mode, ssize_t *size);
|
||||
|
||||
|
||||
/**
|
||||
* Gets resource file data from a zip file.
|
||||
*
|
||||
|
@ -109,7 +109,7 @@ public:
|
|||
* @warning Recall: you are responsible for calling free() on any Non-nullptr pointer returned.
|
||||
*/
|
||||
virtual unsigned char* getFileDataFromZip(const std::string& zipFilePath, const std::string& filename, ssize_t *size);
|
||||
|
||||
|
||||
|
||||
/** Returns the fullpath for a given filename.
|
||||
|
||||
|
@ -119,50 +119,50 @@ public:
|
|||
The file search is based on the array element order of search paths and resolution directories.
|
||||
|
||||
For instance:
|
||||
|
||||
We set two elements("/mnt/sdcard/", "internal_dir/") to search paths vector by setSearchPaths,
|
||||
and set three elements("resources-ipadhd/", "resources-ipad/", "resources-iphonehd")
|
||||
to resolutions vector by setSearchResolutionsOrder. The "internal_dir" is relative to "Resources/".
|
||||
|
||||
If we have a file named 'sprite.png', the mapping in fileLookup dictionary contains `key: sprite.png -> value: sprite.pvr.gz`.
|
||||
Firstly, it will replace 'sprite.png' with 'sprite.pvr.gz', then searching the file sprite.pvr.gz as follows:
|
||||
|
||||
/mnt/sdcard/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/sprite.pvr.gz (if not found, return "sprite.png")
|
||||
|
||||
If the filename contains relative path like "gamescene/uilayer/sprite.png",
|
||||
and the mapping in fileLookup dictionary contains `key: gamescene/uilayer/sprite.png -> value: gamescene/uilayer/sprite.pvr.gz`.
|
||||
The file search order will be:
|
||||
|
||||
/mnt/sdcard/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/gamescene/uilayer/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/sprite.pvr.gz (if not found, return "gamescene/uilayer/sprite.png")
|
||||
|
||||
|
||||
We set two elements("/mnt/sdcard/", "internal_dir/") to search paths vector by setSearchPaths,
|
||||
and set three elements("resources-ipadhd/", "resources-ipad/", "resources-iphonehd")
|
||||
to resolutions vector by setSearchResolutionsOrder. The "internal_dir" is relative to "Resources/".
|
||||
|
||||
If we have a file named 'sprite.png', the mapping in fileLookup dictionary contains `key: sprite.png -> value: sprite.pvr.gz`.
|
||||
Firstly, it will replace 'sprite.png' with 'sprite.pvr.gz', then searching the file sprite.pvr.gz as follows:
|
||||
|
||||
/mnt/sdcard/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/sprite.pvr.gz (if not found, return "sprite.png")
|
||||
|
||||
If the filename contains relative path like "gamescene/uilayer/sprite.png",
|
||||
and the mapping in fileLookup dictionary contains `key: gamescene/uilayer/sprite.png -> value: gamescene/uilayer/sprite.pvr.gz`.
|
||||
The file search order will be:
|
||||
|
||||
/mnt/sdcard/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/gamescene/uilayer/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/sprite.pvr.gz (if not found, return "gamescene/uilayer/sprite.png")
|
||||
|
||||
If the new file can't be found on the file system, it will return the parameter 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 different resources for a given file in the different platforms.
|
||||
|
||||
|
||||
@since v2.1
|
||||
*/
|
||||
virtual std::string fullPathForFilename(const std::string &filename);
|
||||
|
||||
/**
|
||||
* Loads the filenameLookup dictionary from the contents of a filename.
|
||||
*
|
||||
*
|
||||
* @note The plist file name should follow the format below:
|
||||
*
|
||||
*
|
||||
* @code
|
||||
* <?xml version="1.0" encoding="UTF-8"?>
|
||||
* <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
|
@ -193,7 +193,7 @@ public:
|
|||
*/
|
||||
virtual void loadFilenameLookupDictionaryFromFile(const std::string &filename);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sets the filenameLookup dictionary.
|
||||
*
|
||||
* @param pFilenameLookupDict The dictionary for replacing filename.
|
||||
|
@ -211,8 +211,8 @@ public:
|
|||
*
|
||||
*/
|
||||
virtual std::string fullPathFromRelativeFile(const std::string &filename, const std::string &relativeFile);
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Sets the array that contains the search order of the resources.
|
||||
*
|
||||
* @param searchResolutionsOrder The source array that contains the search order of the resources.
|
||||
|
@ -222,14 +222,14 @@ public:
|
|||
* @lua NA
|
||||
*/
|
||||
virtual void setSearchResolutionsOrder(const std::vector<std::string>& searchResolutionsOrder);
|
||||
|
||||
|
||||
/**
|
||||
* Append search order of the resources.
|
||||
*
|
||||
* @see setSearchResolutionsOrder(), fullPathForFilename().
|
||||
* @since v2.1
|
||||
*/
|
||||
virtual void addSearchResolutionsOrder(const std::string &order,const bool front=false);
|
||||
* Append search order of the resources.
|
||||
*
|
||||
* @see setSearchResolutionsOrder(), fullPathForFilename().
|
||||
* @since v2.1
|
||||
*/
|
||||
virtual void addSearchResolutionsOrder(const std::string &order, const bool front=false);
|
||||
|
||||
/**
|
||||
* Gets the array that contains the search order of the resources.
|
||||
|
@ -240,9 +240,9 @@ public:
|
|||
*/
|
||||
virtual const std::vector<std::string>& getSearchResolutionsOrder();
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sets the array of search paths.
|
||||
*
|
||||
*
|
||||
* You can use this array to modify the search path of the resources.
|
||||
* If you want to use "themes" or search resources in the "cache", you can do it easily by adding new entries in this array.
|
||||
*
|
||||
|
@ -262,21 +262,21 @@ public:
|
|||
virtual void setSearchPaths(const std::vector<std::string>& searchPaths);
|
||||
|
||||
/**
|
||||
* Add search path.
|
||||
*
|
||||
* @since v2.1
|
||||
*/
|
||||
* Add search path.
|
||||
*
|
||||
* @since v2.1
|
||||
*/
|
||||
void addSearchPath(const std::string & path, const bool front=false);
|
||||
|
||||
/**
|
||||
* Gets the array of search paths.
|
||||
*
|
||||
*
|
||||
* @return The array of search paths.
|
||||
* @see fullPathForFilename(const char*).
|
||||
* @lua NA
|
||||
*/
|
||||
virtual const std::vector<std::string>& getSearchPaths() const;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the writable path.
|
||||
* @return The path that can be write/read a file in
|
||||
|
@ -386,7 +386,7 @@ public:
|
|||
|
||||
/** Returns the full path cache */
|
||||
const std::unordered_map<std::string, std::string>& getFullPathCache() const { return _fullPathCache; }
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The default constructor.
|
||||
|
@ -468,7 +468,7 @@ protected:
|
|||
*/
|
||||
ValueMap _filenameLookupDict;
|
||||
|
||||
/**
|
||||
/**
|
||||
* The vector contains resolution folders.
|
||||
* The lower index of the element in this vector, the higher priority for this resolution directory.
|
||||
*/
|
||||
|
@ -490,7 +490,7 @@ protected:
|
|||
std::string _defaultResRootPath;
|
||||
|
||||
/**
|
||||
* The full path cache. When a file is found, it will be added into this cache.
|
||||
* The full path cache. When a file is found, it will be added into this cache.
|
||||
* This variable is used for improving the performance of file search.
|
||||
*/
|
||||
std::unordered_map<std::string, std::string> _fullPathCache;
|
||||
|
|
|
@ -770,11 +770,11 @@ int LuaEngine::handleEvent(ScriptHandlerMgr::HandlerType type,void* data)
|
|||
return handleTableViewEvent(type, data);
|
||||
}
|
||||
break;
|
||||
case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS:
|
||||
case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_ERROR:
|
||||
case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_SUCCESS:
|
||||
case ScriptHandlerMgr::HandlerType::ASSETSMANAGEREX_PROGRESS:
|
||||
case ScriptHandlerMgr::HandlerType::ASSETSMANAGEREX_ERROR:
|
||||
case ScriptHandlerMgr::HandlerType::ASSETSMANAGEREX_SUCCESS:
|
||||
{
|
||||
return handleAssetsManagerEvent(type, data);
|
||||
return handleAssetsManagerExEvent(type, data);
|
||||
}
|
||||
break;
|
||||
case ScriptHandlerMgr::HandlerType::ARMATURE_EVENT:
|
||||
|
@ -947,7 +947,7 @@ int LuaEngine::handleTableViewEvent(ScriptHandlerMgr::HandlerType handlerType,vo
|
|||
return ret;
|
||||
}
|
||||
|
||||
int LuaEngine::handleAssetsManagerEvent(ScriptHandlerMgr::HandlerType type,void* data)
|
||||
int LuaEngine::handleAssetsManagerExEvent(ScriptHandlerMgr::HandlerType type,void* data)
|
||||
{
|
||||
if (nullptr == data)
|
||||
return 0;
|
||||
|
@ -956,35 +956,35 @@ int LuaEngine::handleAssetsManagerEvent(ScriptHandlerMgr::HandlerType type,void*
|
|||
if (nullptr == eventData->nativeObject || nullptr == eventData->value)
|
||||
return 0;
|
||||
|
||||
LuaAssetsManagerEventData* assetsManagerData = static_cast<LuaAssetsManagerEventData*>(eventData->value);
|
||||
// LuaAssetsManagerEventData* assetsManagerData = static_cast<LuaAssetsManagerEventData*>(eventData->value);
|
||||
//
|
||||
// int handler = ScriptHandlerMgr::getInstance()->getObjectHandler((void*)eventData->nativeObject, type);
|
||||
//
|
||||
// if (0 == handler)
|
||||
// return 0;
|
||||
//
|
||||
// int ret = 0;
|
||||
// switch (type)
|
||||
// {
|
||||
// case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS:
|
||||
// case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_ERROR:
|
||||
// {
|
||||
// _stack->pushInt(assetsManagerData->value);
|
||||
// ret = _stack->executeFunctionByHandler(handler, 1);
|
||||
// }
|
||||
// break;
|
||||
//
|
||||
// case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_SUCCESS:
|
||||
// {
|
||||
// ret = _stack->executeFunctionByHandler(handler, 0);
|
||||
// }
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
int handler = ScriptHandlerMgr::getInstance()->getObjectHandler((void*)eventData->nativeObject, type);
|
||||
|
||||
if (0 == handler)
|
||||
return 0;
|
||||
|
||||
int ret = 0;
|
||||
switch (type)
|
||||
{
|
||||
case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS:
|
||||
case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_ERROR:
|
||||
{
|
||||
_stack->pushInt(assetsManagerData->value);
|
||||
ret = _stack->executeFunctionByHandler(handler, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_SUCCESS:
|
||||
{
|
||||
ret = _stack->executeFunctionByHandler(handler, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaEngine::handleArmatureWrapper(ScriptHandlerMgr::HandlerType type,void* data)
|
||||
|
|
|
@ -146,7 +146,7 @@ private:
|
|||
int handleTouchesEvent(void* data);
|
||||
int handlerControlEvent(void* data);
|
||||
int handleEvenCustom(void* data);
|
||||
int handleAssetsManagerEvent(ScriptHandlerMgr::HandlerType type,void* data);
|
||||
int handleAssetsManagerExEvent(ScriptHandlerMgr::HandlerType type,void* data);
|
||||
int handleTableViewEvent(ScriptHandlerMgr::HandlerType type,void* data);
|
||||
int handleTableViewEvent(ScriptHandlerMgr::HandlerType type,void* data, int numResults, const std::function<void(lua_State*,int)>& func);
|
||||
int handleArmatureWrapper(ScriptHandlerMgr::HandlerType type,void* data);
|
||||
|
|
|
@ -126,9 +126,9 @@ public:
|
|||
|
||||
XMLHTTPREQUEST_READY_STATE_CHANGE,
|
||||
|
||||
ASSETSMANAGER_PROGRESS,
|
||||
ASSETSMANAGER_SUCCESS,
|
||||
ASSETSMANAGER_ERROR,
|
||||
ASSETSMANAGEREX_PROGRESS,
|
||||
ASSETSMANAGEREX_SUCCESS,
|
||||
ASSETSMANAGEREX_ERROR,
|
||||
|
||||
STUDIO_EVENT_LISTENER,
|
||||
ARMATURE_EVENT,
|
||||
|
|
|
@ -366,35 +366,35 @@ public:
|
|||
|
||||
virtual void onProgress(int percent) override
|
||||
{
|
||||
int handler = ScriptHandlerMgr::getInstance()->getObjectHandler((void*)this, ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS);
|
||||
if (0 != handler)
|
||||
{
|
||||
LuaAssetsManagerEventData eventData(percent);
|
||||
BasicScriptData data((void*)this,&eventData);
|
||||
LuaEngine::getInstance()->handleEvent(ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS, (void*)&data);
|
||||
}
|
||||
// int handler = ScriptHandlerMgr::getInstance()->getObjectHandler((void*)this, ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS);
|
||||
// if (0 != handler)
|
||||
// {
|
||||
// LuaAssetsManagerEventData eventData(percent);
|
||||
// BasicScriptData data((void*)this,&eventData);
|
||||
// LuaEngine::getInstance()->handleEvent(ScriptHandlerMgr::HandlerType::ASSETSMANAGEREX_PROGRESS, (void*)&data);
|
||||
// }
|
||||
}
|
||||
|
||||
virtual void onSuccess() override
|
||||
{
|
||||
int handler = ScriptHandlerMgr::getInstance()->getObjectHandler((void*)this, ScriptHandlerMgr::HandlerType::ASSETSMANAGER_SUCCESS);
|
||||
if (0 != handler)
|
||||
{
|
||||
LuaAssetsManagerEventData eventData;
|
||||
BasicScriptData data((void*)this,&eventData);
|
||||
LuaEngine::getInstance()->handleEvent(ScriptHandlerMgr::HandlerType::ASSETSMANAGER_SUCCESS, (void*)&data);
|
||||
}
|
||||
// int handler = ScriptHandlerMgr::getInstance()->getObjectHandler((void*)this, ScriptHandlerMgr::HandlerType::ASSETSMANAGER_SUCCESS);
|
||||
// if (0 != handler)
|
||||
// {
|
||||
// LuaAssetsManagerEventData eventData;
|
||||
// BasicScriptData data((void*)this,&eventData);
|
||||
// LuaEngine::getInstance()->handleEvent(ScriptHandlerMgr::HandlerType::ASSETSMANAGEREX_SUCCESS, (void*)&data);
|
||||
// }
|
||||
}
|
||||
|
||||
virtual void onError(AssetsManager::ErrorCode errorCode) override
|
||||
{
|
||||
int handler = ScriptHandlerMgr::getInstance()->getObjectHandler((void*)this, ScriptHandlerMgr::HandlerType::ASSETSMANAGER_ERROR);
|
||||
if (0 != handler)
|
||||
{
|
||||
LuaAssetsManagerEventData eventData((int)errorCode);
|
||||
BasicScriptData data((void*)this,&eventData);
|
||||
LuaEngine::getInstance()->handleEvent(ScriptHandlerMgr::HandlerType::ASSETSMANAGER_ERROR, (void*)&data);
|
||||
}
|
||||
// int handler = ScriptHandlerMgr::getInstance()->getObjectHandler((void*)this, ScriptHandlerMgr::HandlerType::ASSETSMANAGER_ERROR);
|
||||
// if (0 != handler)
|
||||
// {
|
||||
// LuaAssetsManagerEventData eventData((int)errorCode);
|
||||
// BasicScriptData data((void*)this,&eventData);
|
||||
// LuaEngine::getInstance()->handleEvent(ScriptHandlerMgr::HandlerType::ASSETSMANAGEREX_ERROR, (void*)&data);
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -445,7 +445,7 @@ static int lua_cocos2dx_AssetsManager_setDelegate(lua_State* L)
|
|||
}
|
||||
|
||||
LUA_FUNCTION handler = toluafix_ref_function(L, 2, 0);
|
||||
ScriptHandlerMgr::HandlerType handlerType = (ScriptHandlerMgr::HandlerType) ((int)tolua_tonumber(L,3,0) + (int)ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS);
|
||||
ScriptHandlerMgr::HandlerType handlerType = (ScriptHandlerMgr::HandlerType) ((int)tolua_tonumber(L,3,0) + (int)ScriptHandlerMgr::HandlerType::ASSETSMANAGEREX_PROGRESS);
|
||||
|
||||
ScriptHandlerMgr::getInstance()->addObjectHandler((void*)delegate, handler, handlerType);
|
||||
return 0;
|
||||
|
@ -939,12 +939,81 @@ static void extendTableView(lua_State* L)
|
|||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
static void extendManifest(lua_State* L)
|
||||
{
|
||||
lua_pushstring(L, "cc.Manifest");
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
static int lua_cocos2dx_Extension_EventListenerAssetsManagerEx_create(lua_State* L)
|
||||
{
|
||||
if (nullptr == L)
|
||||
return 0;
|
||||
|
||||
int argc = 0;
|
||||
|
||||
#if COCOS2D_DEBUG >= 1
|
||||
tolua_Error tolua_err;
|
||||
if (!tolua_isusertable(L,1,"cc.EventListenerAssetsManagerEx",0,&tolua_err)) goto tolua_lerror;
|
||||
#endif
|
||||
|
||||
argc = lua_gettop(L)-1;
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
|
||||
#if COCOS2D_DEBUG >= 1
|
||||
if (!tolua_isusertype(L, 2, "cc.AssetsManagerEx", 0, &tolua_err) ||
|
||||
!toluafix_isfunction(L,3,"LUA_FUNCTION",0,&tolua_err))
|
||||
goto tolua_lerror;
|
||||
#endif
|
||||
cocos2d::extension::AssetsManagerEx* assetManager = static_cast<cocos2d::extension::AssetsManagerEx*>(tolua_tousertype(L,2,nullptr));
|
||||
|
||||
LUA_FUNCTION handler = toluafix_ref_function(L,3,0);
|
||||
|
||||
cocos2d::extension::EventListenerAssetsManagerEx* ret = cocos2d::extension::EventListenerAssetsManagerEx::create(assetManager, [=](EventAssetsManagerEx* event){
|
||||
int id = event? (int)event->_ID : -1;
|
||||
int* luaID = event? &event->_luaID : nullptr;
|
||||
toluafix_pushusertype_ccobject(L, id, luaID, (void*)event,"cc.EventAssetsManagerEx");
|
||||
LuaEngine::getInstance()->getLuaStack()->executeFunctionByHandler(handler, 1);
|
||||
});
|
||||
|
||||
int id = (ret) ? (int)ret->_ID : -1;
|
||||
int* luaID = (ret) ? &ret->_luaID : nullptr;
|
||||
toluafix_pushusertype_ccobject(L, id, luaID, (void*)ret,"cc.EventListenerAssetsManagerEx");
|
||||
return 1;
|
||||
}
|
||||
|
||||
CCLOG("%s has wrong number of arguments: %d, was expecting %d \n", "create",argc, 2);
|
||||
return 0;
|
||||
|
||||
#if COCOS2D_DEBUG >= 1
|
||||
tolua_lerror:
|
||||
tolua_error(L,"#ferror in function 'lua_cocos2dx_Extension_EventListenerAssetsManagerEx_create'.",&tolua_err);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void extendEventListenerAssetsManagerEx(lua_State* L)
|
||||
{
|
||||
lua_pushstring(L, "cc.EventListenerAssetsManagerEx");
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
if (lua_istable(L,-1))
|
||||
{
|
||||
tolua_function(L, "create", lua_cocos2dx_Extension_EventListenerAssetsManagerEx_create);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
int register_all_cocos2dx_extension_manual(lua_State* tolua_S)
|
||||
{
|
||||
extendControl(tolua_S);
|
||||
extendAssetsManager(tolua_S);
|
||||
extendScrollView(tolua_S);
|
||||
extendTableView(tolua_S);
|
||||
extendManifest(tolua_S);
|
||||
extendEventListenerAssetsManagerEx(tolua_S);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,15 +35,6 @@ extern "C" {
|
|||
TOLUA_API int register_all_cocos2dx_extension_manual(lua_State* tolua_S);
|
||||
TOLUA_API int register_extension_module(lua_State* tolua_S);
|
||||
|
||||
struct LuaAssetsManagerEventData
|
||||
{
|
||||
int value;
|
||||
|
||||
LuaAssetsManagerEventData(int _value = 0):value(_value)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct LuaTableViewEventData
|
||||
{
|
||||
void* value;
|
||||
|
|
|
@ -208,6 +208,39 @@ cc.NODE_ON_ENTER_TRANSITION_DID_FINISH = 2
|
|||
cc.NODE_ON_EXIT_TRANSITION_DID_START = 3
|
||||
cc.NODE_ON_CLEAN_UP = 4
|
||||
|
||||
cc.CONTROL_STEPPER_PART_MINUS = 0
|
||||
cc.CONTROL_STEPPER_PART_PLUS = 1
|
||||
cc.CONTROL_STEPPER_PART_NONE = 2
|
||||
|
||||
cc.TABLEVIEW_FILL_TOPDOWN = 0
|
||||
cc.TABLEVIEW_FILL_BOTTOMUP = 1
|
||||
|
||||
cc.WEBSOCKET_OPEN = 0
|
||||
cc.WEBSOCKET_MESSAGE = 1
|
||||
cc.WEBSOCKET_CLOSE = 2
|
||||
cc.WEBSOCKET_ERROR = 3
|
||||
|
||||
cc.WEBSOCKET_STATE_CONNECTING = 0
|
||||
cc.WEBSOCKET_STATE_OPEN = 1
|
||||
cc.WEBSOCKET_STATE_CLOSING = 2
|
||||
cc.WEBSOCKET_STATE_CLOSED = 3
|
||||
|
||||
|
||||
cc.XMLHTTPREQUEST_RESPONSE_STRING = 0
|
||||
cc.XMLHTTPREQUEST_RESPONSE_ARRAY_BUFFER = 1
|
||||
cc.XMLHTTPREQUEST_RESPONSE_BLOB = 2
|
||||
cc.XMLHTTPREQUEST_RESPONSE_DOCUMENT = 3
|
||||
cc.XMLHTTPREQUEST_RESPONSE_JSON = 4
|
||||
|
||||
cc.ASSETSMANAGEREX_CREATE_FILE = 0
|
||||
cc.ASSETSMANAGEREX_NETWORK = 1
|
||||
cc.ASSETSMANAGEREX_NO_NEW_VERSION = 2
|
||||
cc.ASSETSMANAGEREX_UNCOMPRESS = 3
|
||||
|
||||
cc.ASSETSMANAGEREX_PROTOCOL_PROGRESS = 0
|
||||
cc.ASSETSMANAGEREX_PROTOCOL_SUCCESS = 1
|
||||
cc.ASSETSMANAGEREX_PROTOCOL_ERROR = 2
|
||||
|
||||
cc.Handler = cc.Handler or {}
|
||||
cc.Handler.NODE = 0
|
||||
cc.Handler.MENU_CLICKED = 1
|
||||
|
@ -477,7 +510,6 @@ cc.KeyCodeKey =
|
|||
|
||||
cc.KeyCode =
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
for k,v in ipairs(cc.KeyCodeKey) do
|
||||
|
@ -486,6 +518,28 @@ end
|
|||
|
||||
cc.KeyCode.KEY_BACK = cc.KeyCode.KEY_ESCAPE
|
||||
|
||||
cc.EventAssetsManagerEx =
|
||||
{
|
||||
EventCode =
|
||||
{
|
||||
ERROR_NO_LOCAL_MANIFEST = 0,
|
||||
ERROR_DOWNLOAD_MANIFEST = 1,
|
||||
ERROR_PARSE_MANIFEST = 2,
|
||||
NEW_VERSION_FOUND = 3,
|
||||
ALREADY_UP_TO_DATE = 4,
|
||||
UPDATE_PROGRESSION = 5,
|
||||
ASSET_UPDATED = 6,
|
||||
ERROR_UPDATING = 7,
|
||||
UPDATE_FINISHED = 8,
|
||||
},
|
||||
}
|
||||
|
||||
cc.AssetsManagerExStatic =
|
||||
{
|
||||
VERSION_ID = "@version",
|
||||
MANIFEST_ID = "@manifest",
|
||||
}
|
||||
|
||||
cc.EventCode =
|
||||
{
|
||||
BEGAN = 0,
|
||||
|
|
|
@ -7,6 +7,11 @@ LOCAL_MODULE_FILENAME := libextension
|
|||
|
||||
LOCAL_SRC_FILES := \
|
||||
assets-manager/AssetsManager.cpp \
|
||||
assets-manager/Downloader.cpp \
|
||||
assets-manager/Manifest.cpp \
|
||||
assets-manager/AssetsManagerEx.cpp \
|
||||
assets-manager/CCEventAssetsManagerEx.cpp \
|
||||
assets-manager/CCEventListenerAssetsManagerEx.cpp \
|
||||
GUI/CCControlExtension/CCControl.cpp \
|
||||
GUI/CCControlExtension/CCControlButton.cpp \
|
||||
GUI/CCControlExtension/CCControlColourPicker.cpp \
|
||||
|
|
|
@ -22,6 +22,11 @@ include_directories(
|
|||
set(COCOS_EXTENSIONS_SRC
|
||||
|
||||
../extensions/assets-manager/AssetsManager.cpp
|
||||
../extensions/assets-manager/AssetsManagerEx.cpp
|
||||
../extensions/assets-manager/CCEventAssetsManagerEx.cpp
|
||||
../extensions/assets-manager/CCEventListenerAssetsManagerEx.cpp
|
||||
../extensions/assets-manager/Downloader.cpp
|
||||
../extensions/assets-manager/Manifest.cpp
|
||||
../extensions/GUI/CCControlExtension/CCControl.cpp
|
||||
../extensions/GUI/CCControlExtension/CCControlButton.cpp
|
||||
../extensions/GUI/CCControlExtension/CCControlColourPicker.cpp
|
||||
|
|
|
@ -0,0 +1,877 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "AssetsManagerEx.h"
|
||||
#include "CCEventListenerAssetsManagerEx.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <curl/easy.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "unzip.h"
|
||||
|
||||
NS_CC_EXT_BEGIN
|
||||
|
||||
#define VERSION_FILENAME "version.manifest"
|
||||
#define TEMP_MANIFEST_FILENAME "project.manifest.temp"
|
||||
#define MANIFEST_FILENAME "project.manifest"
|
||||
|
||||
#define BUFFER_SIZE 8192
|
||||
#define MAX_FILENAME 512
|
||||
|
||||
#define DEFAULT_CONNECTION_TIMEOUT 8
|
||||
|
||||
const std::string AssetsManagerEx::VERSION_ID = "@version";
|
||||
const std::string AssetsManagerEx::MANIFEST_ID = "@manifest";
|
||||
const std::string AssetsManagerEx::BATCH_UPDATE_ID = "@batch_update";
|
||||
|
||||
// Implementation of AssetsManagerEx
|
||||
|
||||
AssetsManagerEx::AssetsManagerEx(const std::string& manifestUrl, const std::string& storagePath)
|
||||
: _updateState(State::UNCHECKED)
|
||||
, _waitToUpdate(false)
|
||||
, _totalToDownload(0)
|
||||
, _totalWaitToDownload(0)
|
||||
, _percent(0)
|
||||
, _percentByFile(0)
|
||||
, _manifestUrl(manifestUrl)
|
||||
, _storagePath("")
|
||||
, _cacheVersionPath("")
|
||||
, _cacheManifestPath("")
|
||||
, _tempManifestPath("")
|
||||
, _assets(nullptr)
|
||||
, _localManifest(nullptr)
|
||||
, _tempManifest(nullptr)
|
||||
, _remoteManifest(nullptr)
|
||||
{
|
||||
// Init variables
|
||||
_eventDispatcher = Director::getInstance()->getEventDispatcher();
|
||||
std::string pointer = StringUtils::format("%p", this);
|
||||
_eventName = EventListenerAssetsManagerEx::LISTENER_ID + pointer;
|
||||
_fileUtils = FileUtils::getInstance();
|
||||
_updateState = State::UNCHECKED;
|
||||
|
||||
_downloader = std::make_shared<Downloader>();
|
||||
_downloader->setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
|
||||
_downloader->_onError = std::bind(&AssetsManagerEx::onError, this, std::placeholders::_1);
|
||||
_downloader->_onProgress = std::bind(&AssetsManagerEx::onProgress,
|
||||
this,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
std::placeholders::_3,
|
||||
std::placeholders::_4);
|
||||
_downloader->_onSuccess = std::bind(&AssetsManagerEx::onSuccess, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||
setStoragePath(storagePath);
|
||||
_cacheVersionPath = _storagePath + VERSION_FILENAME;
|
||||
_cacheManifestPath = _storagePath + MANIFEST_FILENAME;
|
||||
_tempManifestPath = _storagePath + TEMP_MANIFEST_FILENAME;
|
||||
|
||||
// Init and load local manifest
|
||||
_localManifest = new Manifest();
|
||||
loadLocalManifest(manifestUrl);
|
||||
|
||||
// Init and load temporary manifest
|
||||
_tempManifest = new Manifest();
|
||||
_tempManifest->parse(_tempManifestPath);
|
||||
if (!_tempManifest->isLoaded())
|
||||
_fileUtils->removeFile(_tempManifestPath);
|
||||
|
||||
// Init remote manifest for future usage
|
||||
_remoteManifest = new Manifest();
|
||||
}
|
||||
|
||||
AssetsManagerEx::~AssetsManagerEx()
|
||||
{
|
||||
_downloader->_onError = nullptr;
|
||||
_downloader->_onSuccess = nullptr;
|
||||
_downloader->_onProgress = nullptr;
|
||||
CC_SAFE_RELEASE(_localManifest);
|
||||
// _tempManifest could share a ptr with _remoteManifest or _localManifest
|
||||
if (_tempManifest != _localManifest && _tempManifest != _remoteManifest)
|
||||
CC_SAFE_RELEASE(_tempManifest);
|
||||
CC_SAFE_RELEASE(_remoteManifest);
|
||||
}
|
||||
|
||||
AssetsManagerEx* AssetsManagerEx::create(const std::string& manifestUrl, const std::string& storagePath)
|
||||
{
|
||||
AssetsManagerEx* ret = new AssetsManagerEx(manifestUrl, storagePath);
|
||||
if (ret)
|
||||
{
|
||||
ret->autorelease();
|
||||
}
|
||||
else
|
||||
{
|
||||
CC_SAFE_DELETE(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AssetsManagerEx::prepareLocalManifest()
|
||||
{
|
||||
// An alias to assets
|
||||
_assets = &(_localManifest->getAssets());
|
||||
|
||||
// Add search paths
|
||||
_localManifest->prependSearchPaths();
|
||||
}
|
||||
|
||||
void AssetsManagerEx::loadLocalManifest(const std::string& manifestUrl)
|
||||
{
|
||||
// Prefer to use the cached manifest file, if not found use user configured manifest file
|
||||
if (_fileUtils->isFileExist(_cacheManifestPath))
|
||||
{
|
||||
_localManifest->parse(_cacheManifestPath);
|
||||
if (_localManifest->isLoaded())
|
||||
prepareLocalManifest();
|
||||
else
|
||||
_fileUtils->removeFile(_cacheManifestPath);
|
||||
}
|
||||
|
||||
// Fail to found or load cached manifest file
|
||||
if (!_localManifest->isLoaded())
|
||||
{
|
||||
_localManifest->parse(_manifestUrl);
|
||||
if (_localManifest->isLoaded())
|
||||
prepareLocalManifest();
|
||||
}
|
||||
|
||||
// Fail to load local manifest
|
||||
if (!_localManifest->isLoaded())
|
||||
{
|
||||
CCLOG("AssetsManagerEx : No local manifest file found error.\n");
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ERROR_NO_LOCAL_MANIFEST);
|
||||
}
|
||||
}
|
||||
|
||||
std::string AssetsManagerEx::basename(const std::string& path) const
|
||||
{
|
||||
size_t found = path.find_last_of("/\\");
|
||||
|
||||
if (std::string::npos != found)
|
||||
{
|
||||
return path.substr(0, found);
|
||||
}
|
||||
else
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
std::string AssetsManagerEx::get(const std::string& key) const
|
||||
{
|
||||
auto it = _assets->find(key);
|
||||
if (it != _assets->cend()) {
|
||||
return _storagePath + it->second.path;
|
||||
}
|
||||
else return "";
|
||||
}
|
||||
|
||||
const Manifest* AssetsManagerEx::getLocalManifest() const
|
||||
{
|
||||
return _localManifest;
|
||||
}
|
||||
|
||||
const Manifest* AssetsManagerEx::getRemoteManifest() const
|
||||
{
|
||||
return _remoteManifest;
|
||||
}
|
||||
|
||||
const std::string& AssetsManagerEx::getStoragePath() const
|
||||
{
|
||||
return _storagePath;
|
||||
}
|
||||
|
||||
void AssetsManagerEx::setStoragePath(const std::string& storagePath)
|
||||
{
|
||||
if (_storagePath.size() > 0)
|
||||
_fileUtils->removeDirectory(_storagePath);
|
||||
|
||||
_storagePath = storagePath;
|
||||
adjustPath(_storagePath);
|
||||
_fileUtils->createDirectory(_storagePath);
|
||||
}
|
||||
|
||||
void AssetsManagerEx::adjustPath(std::string &path)
|
||||
{
|
||||
if (path.size() > 0 && path[path.size() - 1] != '/')
|
||||
{
|
||||
path.append("/");
|
||||
}
|
||||
}
|
||||
|
||||
bool AssetsManagerEx::decompress(const std::string &zip)
|
||||
{
|
||||
// Find root path for zip file
|
||||
size_t pos = zip.find_last_of("/\\");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
CCLOG("AssetsManagerEx : no root path specified for zip file %s\n", zip.c_str());
|
||||
return false;
|
||||
}
|
||||
const std::string rootPath = zip.substr(0, pos+1);
|
||||
|
||||
// Open the zip file
|
||||
unzFile zipfile = unzOpen(zip.c_str());
|
||||
if (! zipfile)
|
||||
{
|
||||
CCLOG("AssetsManagerEx : can not open downloaded zip file %s\n", zip.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get info about the zip file
|
||||
unz_global_info global_info;
|
||||
if (unzGetGlobalInfo(zipfile, &global_info) != UNZ_OK)
|
||||
{
|
||||
CCLOG("AssetsManagerEx : can not read file global info of %s\n", zip.c_str());
|
||||
unzClose(zipfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Buffer to hold data read from the zip file
|
||||
char readBuffer[BUFFER_SIZE];
|
||||
// Loop to extract all files.
|
||||
uLong i;
|
||||
for (i = 0; i < global_info.number_entry; ++i)
|
||||
{
|
||||
// Get info about current file.
|
||||
unz_file_info fileInfo;
|
||||
char fileName[MAX_FILENAME];
|
||||
if (unzGetCurrentFileInfo(zipfile,
|
||||
&fileInfo,
|
||||
fileName,
|
||||
MAX_FILENAME,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0) != UNZ_OK)
|
||||
{
|
||||
CCLOG("AssetsManagerEx : can not read compressed file info\n");
|
||||
unzClose(zipfile);
|
||||
return false;
|
||||
}
|
||||
const std::string fullPath = rootPath + fileName;
|
||||
|
||||
// Check if this entry is a directory or a file.
|
||||
const size_t filenameLength = strlen(fileName);
|
||||
if (fileName[filenameLength-1] == '/')
|
||||
{
|
||||
//There are not directory entry in some case.
|
||||
//So we need to create directory when decompressing file entry
|
||||
if ( !_fileUtils->createDirectory(basename(fullPath)) )
|
||||
{
|
||||
// Failed to create directory
|
||||
CCLOG("AssetsManagerEx : can not create directory %s\n", fullPath.c_str());
|
||||
unzClose(zipfile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Entry is a file, so extract it.
|
||||
// Open current file.
|
||||
if (unzOpenCurrentFile(zipfile) != UNZ_OK)
|
||||
{
|
||||
CCLOG("AssetsManagerEx : can not extract file %s\n", fileName);
|
||||
unzClose(zipfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a file to store current file.
|
||||
FILE *out = fopen(fullPath.c_str(), "wb");
|
||||
if (!out)
|
||||
{
|
||||
CCLOG("AssetsManagerEx : can not create decompress destination file %s\n", fullPath.c_str());
|
||||
unzCloseCurrentFile(zipfile);
|
||||
unzClose(zipfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write current file content to destinate file.
|
||||
int error = UNZ_OK;
|
||||
do
|
||||
{
|
||||
error = unzReadCurrentFile(zipfile, readBuffer, BUFFER_SIZE);
|
||||
if (error < 0)
|
||||
{
|
||||
CCLOG("AssetsManagerEx : can not read zip file %s, error code is %d\n", fileName, error);
|
||||
fclose(out);
|
||||
unzCloseCurrentFile(zipfile);
|
||||
unzClose(zipfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (error > 0)
|
||||
{
|
||||
fwrite(readBuffer, error, 1, out);
|
||||
}
|
||||
} while(error > 0);
|
||||
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
unzCloseCurrentFile(zipfile);
|
||||
|
||||
// Goto next entry listed in the zip file.
|
||||
if ((i+1) < global_info.number_entry)
|
||||
{
|
||||
if (unzGoToNextFile(zipfile) != UNZ_OK)
|
||||
{
|
||||
CCLOG("AssetsManagerEx : can not read next file for decompressing\n");
|
||||
unzClose(zipfile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unzClose(zipfile);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssetsManagerEx::decompressDownloadedZip()
|
||||
{
|
||||
// Decompress all compressed files
|
||||
for (auto it = _compressedFiles.begin(); it != _compressedFiles.end(); ++it) {
|
||||
std::string zipfile = *it;
|
||||
if (!decompress(zipfile))
|
||||
{
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ERROR_DECOMPRESS, "", "Unable to decompress file " + zipfile);
|
||||
}
|
||||
_fileUtils->removeFile(zipfile);
|
||||
}
|
||||
_compressedFiles.clear();
|
||||
}
|
||||
|
||||
void AssetsManagerEx::dispatchUpdateEvent(EventAssetsManagerEx::EventCode code, const std::string &assetId/* = ""*/, const std::string &message/* = ""*/, int curle_code/* = CURLE_OK*/, int curlm_code/* = CURLM_OK*/)
|
||||
{
|
||||
EventAssetsManagerEx event(_eventName, this, code, _percent, _percentByFile, assetId, message, curle_code, curlm_code);
|
||||
_eventDispatcher->dispatchEvent(&event);
|
||||
}
|
||||
|
||||
AssetsManagerEx::State AssetsManagerEx::getState() const
|
||||
{
|
||||
return _updateState;
|
||||
}
|
||||
|
||||
void AssetsManagerEx::downloadVersion()
|
||||
{
|
||||
if (_updateState > State::PREDOWNLOAD_VERSION)
|
||||
return;
|
||||
|
||||
std::string versionUrl = _localManifest->getVersionFileUrl();
|
||||
|
||||
if (versionUrl.size() > 0)
|
||||
{
|
||||
_updateState = State::DOWNLOADING_VERSION;
|
||||
// Download version file asynchronously
|
||||
_downloader->downloadAsync(versionUrl, _cacheVersionPath, VERSION_ID);
|
||||
}
|
||||
// No version file found
|
||||
else
|
||||
{
|
||||
CCLOG("AssetsManagerEx : No version file found, step skipped\n");
|
||||
_updateState = State::PREDOWNLOAD_MANIFEST;
|
||||
downloadManifest();
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerEx::parseVersion()
|
||||
{
|
||||
if (_updateState != State::VERSION_LOADED)
|
||||
return;
|
||||
|
||||
_remoteManifest->parse(_cacheVersionPath);
|
||||
|
||||
if (!_remoteManifest->isVersionLoaded())
|
||||
{
|
||||
CCLOG("AssetsManagerEx : Fail to parse version file, step skipped\n");
|
||||
_updateState = State::PREDOWNLOAD_MANIFEST;
|
||||
downloadManifest();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_localManifest->versionEquals(_remoteManifest))
|
||||
{
|
||||
_updateState = State::UP_TO_DATE;
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ALREADY_UP_TO_DATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
_updateState = State::NEED_UPDATE;
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::NEW_VERSION_FOUND);
|
||||
|
||||
// Wait to update so continue the process
|
||||
if (_waitToUpdate)
|
||||
{
|
||||
_updateState = State::PREDOWNLOAD_MANIFEST;
|
||||
downloadManifest();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerEx::downloadManifest()
|
||||
{
|
||||
if (_updateState != State::PREDOWNLOAD_MANIFEST)
|
||||
return;
|
||||
|
||||
std::string manifestUrl = _localManifest->getManifestFileUrl();
|
||||
if (manifestUrl.size() > 0)
|
||||
{
|
||||
_updateState = State::DOWNLOADING_MANIFEST;
|
||||
// Download version file asynchronously
|
||||
_downloader->downloadAsync(manifestUrl, _tempManifestPath, MANIFEST_ID);
|
||||
}
|
||||
// No manifest file found
|
||||
else
|
||||
{
|
||||
CCLOG("AssetsManagerEx : No manifest file found, check update failed\n");
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ERROR_DOWNLOAD_MANIFEST);
|
||||
_updateState = State::UNCHECKED;
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerEx::parseManifest()
|
||||
{
|
||||
if (_updateState != State::MANIFEST_LOADED)
|
||||
return;
|
||||
|
||||
_remoteManifest->parse(_tempManifestPath);
|
||||
|
||||
if (!_remoteManifest->isLoaded())
|
||||
{
|
||||
CCLOG("AssetsManagerEx : Error parsing manifest file\n");
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ERROR_PARSE_MANIFEST);
|
||||
_updateState = State::UNCHECKED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_localManifest->versionEquals(_remoteManifest))
|
||||
{
|
||||
_updateState = State::UP_TO_DATE;
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ALREADY_UP_TO_DATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
_updateState = State::NEED_UPDATE;
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::NEW_VERSION_FOUND);
|
||||
|
||||
if (_waitToUpdate)
|
||||
{
|
||||
startUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerEx::startUpdate()
|
||||
{
|
||||
if (_updateState != State::NEED_UPDATE)
|
||||
return;
|
||||
|
||||
_updateState = State::UPDATING;
|
||||
// Clean up before update
|
||||
_failedUnits.clear();
|
||||
_downloadUnits.clear();
|
||||
_compressedFiles.clear();
|
||||
_totalWaitToDownload = _totalToDownload = 0;
|
||||
_percent = _percentByFile = _sizeCollected = _totalSize = 0;
|
||||
_downloadedSize.clear();
|
||||
_totalEnabled = false;
|
||||
|
||||
// Temporary manifest exists, resuming previous download
|
||||
if (_tempManifest->isLoaded() && _tempManifest->versionEquals(_remoteManifest))
|
||||
{
|
||||
_tempManifest->genResumeAssetsList(&_downloadUnits);
|
||||
|
||||
_totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size();
|
||||
_downloader->batchDownloadAsync(_downloadUnits, BATCH_UPDATE_ID);
|
||||
|
||||
std::string msg = StringUtils::format("Resuming from previous unfinished update, %d files remains to be finished.", _totalToDownload);
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg);
|
||||
}
|
||||
// Check difference
|
||||
else
|
||||
{
|
||||
// Temporary manifest not exists,
|
||||
// it will be used to register the download states of each asset,
|
||||
// in this case, it equals remote manifest.
|
||||
if(!_tempManifest->isLoaded()) {
|
||||
_tempManifest->release();
|
||||
_tempManifest = _remoteManifest;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, Manifest::AssetDiff> diff_map = _localManifest->genDiff(_remoteManifest);
|
||||
if (diff_map.size() == 0)
|
||||
{
|
||||
_updateState = State::UP_TO_DATE;
|
||||
// Rename temporary manifest to valid manifest
|
||||
_fileUtils->renameFile(_storagePath, TEMP_MANIFEST_FILENAME, MANIFEST_FILENAME);
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ALREADY_UP_TO_DATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generate download units for all assets that need to be updated or added
|
||||
std::string packageUrl = _remoteManifest->getPackageUrl();
|
||||
for (auto it = diff_map.begin(); it != diff_map.end(); ++it)
|
||||
{
|
||||
Manifest::AssetDiff diff = it->second;
|
||||
|
||||
if (diff.type == Manifest::DiffType::DELETED)
|
||||
{
|
||||
_fileUtils->removeFile(_storagePath + diff.asset.path);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string path = diff.asset.path;
|
||||
// Create path
|
||||
_fileUtils->createDirectory(basename(_storagePath + path));
|
||||
|
||||
Downloader::DownloadUnit unit;
|
||||
unit.customId = it->first;
|
||||
unit.srcUrl = packageUrl + path;
|
||||
unit.storagePath = _storagePath + path;
|
||||
unit.resumeDownload = false;
|
||||
_downloadUnits.emplace(unit.customId, unit);
|
||||
}
|
||||
}
|
||||
// Set other assets' downloadState to SUCCESSED
|
||||
auto assets = _remoteManifest->getAssets();
|
||||
for (auto it = assets.cbegin(); it != assets.cend(); ++it)
|
||||
{
|
||||
const std::string &key = it->first;
|
||||
auto diffIt = diff_map.find(key);
|
||||
if (diffIt == diff_map.end())
|
||||
{
|
||||
_tempManifest->setAssetDownloadState(key, Manifest::DownloadState::SUCCESSED);
|
||||
}
|
||||
}
|
||||
|
||||
_totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size();
|
||||
_downloader->batchDownloadAsync(_downloadUnits, BATCH_UPDATE_ID);
|
||||
|
||||
std::string msg = StringUtils::format("Start to update %d files from remote package.", _totalToDownload);
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg);
|
||||
}
|
||||
}
|
||||
|
||||
_waitToUpdate = false;
|
||||
}
|
||||
|
||||
void AssetsManagerEx::updateSucceed()
|
||||
{
|
||||
// Every thing is correctly downloaded, do the following
|
||||
// 1. rename temporary manifest to valid manifest
|
||||
_fileUtils->renameFile(_storagePath, TEMP_MANIFEST_FILENAME, MANIFEST_FILENAME);
|
||||
// 2. swap the localManifest
|
||||
if (_localManifest != nullptr)
|
||||
_localManifest->release();
|
||||
_localManifest = _remoteManifest;
|
||||
_remoteManifest = nullptr;
|
||||
// 3. make local manifest take effect
|
||||
prepareLocalManifest();
|
||||
// 4. decompress all compressed files
|
||||
decompressDownloadedZip();
|
||||
// 5. Set update state
|
||||
_updateState = State::UP_TO_DATE;
|
||||
// 6. Notify finished event
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_FINISHED);
|
||||
}
|
||||
|
||||
void AssetsManagerEx::checkUpdate()
|
||||
{
|
||||
if (!_localManifest->isLoaded())
|
||||
{
|
||||
CCLOG("AssetsManagerEx : No local manifest file found error.\n");
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ERROR_NO_LOCAL_MANIFEST);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_updateState) {
|
||||
case State::UNCHECKED:
|
||||
case State::PREDOWNLOAD_VERSION:
|
||||
{
|
||||
downloadVersion();
|
||||
}
|
||||
break;
|
||||
case State::UP_TO_DATE:
|
||||
{
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ALREADY_UP_TO_DATE);
|
||||
}
|
||||
break;
|
||||
case State::FAIL_TO_UPDATE:
|
||||
case State::NEED_UPDATE:
|
||||
{
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::NEW_VERSION_FOUND);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerEx::update()
|
||||
{
|
||||
if (!_localManifest->isLoaded())
|
||||
{
|
||||
CCLOG("AssetsManagerEx : No local manifest file found error.\n");
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ERROR_NO_LOCAL_MANIFEST);
|
||||
return;
|
||||
}
|
||||
|
||||
_waitToUpdate = true;
|
||||
|
||||
switch (_updateState) {
|
||||
case State::UNCHECKED:
|
||||
{
|
||||
_updateState = State::PREDOWNLOAD_VERSION;
|
||||
}
|
||||
case State::PREDOWNLOAD_VERSION:
|
||||
{
|
||||
downloadVersion();
|
||||
}
|
||||
break;
|
||||
case State::VERSION_LOADED:
|
||||
{
|
||||
parseVersion();
|
||||
}
|
||||
break;
|
||||
case State::PREDOWNLOAD_MANIFEST:
|
||||
{
|
||||
downloadManifest();
|
||||
}
|
||||
break;
|
||||
case State::MANIFEST_LOADED:
|
||||
{
|
||||
parseManifest();
|
||||
}
|
||||
break;
|
||||
case State::FAIL_TO_UPDATE:
|
||||
case State::NEED_UPDATE:
|
||||
{
|
||||
// Manifest not loaded yet
|
||||
if (!_remoteManifest->isLoaded())
|
||||
{
|
||||
_waitToUpdate = true;
|
||||
_updateState = State::PREDOWNLOAD_MANIFEST;
|
||||
downloadManifest();
|
||||
}
|
||||
else
|
||||
{
|
||||
startUpdate();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case State::UP_TO_DATE:
|
||||
case State::UPDATING:
|
||||
_waitToUpdate = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerEx::updateAssets(const Downloader::DownloadUnits& assets)
|
||||
{
|
||||
if (_updateState != State::UPDATING && _localManifest->isLoaded() && _remoteManifest->isLoaded())
|
||||
{
|
||||
int size = (int)(assets.size());
|
||||
if (size > 0)
|
||||
{
|
||||
_updateState = State::UPDATING;
|
||||
_downloadUnits.clear();
|
||||
_downloadUnits = assets;
|
||||
_downloader->batchDownloadAsync(_downloadUnits, BATCH_UPDATE_ID);
|
||||
}
|
||||
else if (size == 0 && _totalWaitToDownload == 0)
|
||||
{
|
||||
updateSucceed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Downloader::DownloadUnits& AssetsManagerEx::getFailedAssets() const
|
||||
{
|
||||
return _failedUnits;
|
||||
}
|
||||
|
||||
void AssetsManagerEx::downloadFailedAssets()
|
||||
{
|
||||
CCLOG("AssetsManagerEx : Start update %lu failed assets.\n", _failedUnits.size());
|
||||
updateAssets(_failedUnits);
|
||||
}
|
||||
|
||||
|
||||
void AssetsManagerEx::onError(const Downloader::Error &error)
|
||||
{
|
||||
// Skip version error occured
|
||||
if (error.customId == VERSION_ID)
|
||||
{
|
||||
CCLOG("AssetsManagerEx : Fail to download version file, step skipped\n");
|
||||
_updateState = State::PREDOWNLOAD_MANIFEST;
|
||||
downloadManifest();
|
||||
}
|
||||
else if (error.customId == MANIFEST_ID)
|
||||
{
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ERROR_DOWNLOAD_MANIFEST, error.customId, error.message, error.curle_code, error.curlm_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto unitIt = _downloadUnits.find(error.customId);
|
||||
// Found unit and add it to failed units
|
||||
if (unitIt != _downloadUnits.end())
|
||||
{
|
||||
Downloader::DownloadUnit unit = unitIt->second;
|
||||
_failedUnits.emplace(unit.customId, unit);
|
||||
}
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ERROR_UPDATING, error.customId, error.message, error.curle_code, error.curlm_code);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerEx::onProgress(double total, double downloaded, const std::string &url, const std::string &customId)
|
||||
{
|
||||
if (customId == VERSION_ID || customId == MANIFEST_ID)
|
||||
{
|
||||
_percent = 100 * (total - downloaded) / total;
|
||||
// Notify progression event
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, customId);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calcul total downloaded
|
||||
bool found = false;
|
||||
double totalDownloaded = 0;
|
||||
for (auto it = _downloadedSize.begin(); it != _downloadedSize.end(); ++it)
|
||||
{
|
||||
if (it->first == customId)
|
||||
{
|
||||
it->second = downloaded;
|
||||
found = true;
|
||||
}
|
||||
totalDownloaded += it->second;
|
||||
}
|
||||
// Collect information if not registed
|
||||
if (!found)
|
||||
{
|
||||
// Set download state to DOWNLOADING, this will run only once in the download process
|
||||
_tempManifest->setAssetDownloadState(customId, Manifest::DownloadState::DOWNLOADING);
|
||||
// Register the download size information
|
||||
_downloadedSize.emplace(customId, downloaded);
|
||||
_totalSize += total;
|
||||
_sizeCollected++;
|
||||
// All collected, enable total size
|
||||
if (_sizeCollected == _totalToDownload)
|
||||
{
|
||||
_totalEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_totalEnabled && _updateState == State::UPDATING)
|
||||
{
|
||||
float currentPercent = 100 * totalDownloaded / _totalSize;
|
||||
// Notify at integer level change
|
||||
if ((int)currentPercent != (int)_percent) {
|
||||
_percent = currentPercent;
|
||||
// Notify progression event
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerEx::onSuccess(const std::string &srcUrl, const std::string &storagePath, const std::string &customId)
|
||||
{
|
||||
if (customId == VERSION_ID)
|
||||
{
|
||||
_updateState = State::VERSION_LOADED;
|
||||
parseVersion();
|
||||
}
|
||||
else if (customId == MANIFEST_ID)
|
||||
{
|
||||
_updateState = State::MANIFEST_LOADED;
|
||||
parseManifest();
|
||||
}
|
||||
else if (customId == BATCH_UPDATE_ID)
|
||||
{
|
||||
// Finished with error check
|
||||
if (_failedUnits.size() > 0 || _totalWaitToDownload > 0)
|
||||
{
|
||||
// Save current download manifest information for resuming
|
||||
_tempManifest->saveToFile(_tempManifestPath);
|
||||
|
||||
decompressDownloadedZip();
|
||||
|
||||
_updateState = State::FAIL_TO_UPDATE;
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_FAILED);
|
||||
}
|
||||
else
|
||||
{
|
||||
updateSucceed();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto assets = _remoteManifest->getAssets();
|
||||
auto assetIt = assets.find(customId);
|
||||
if (assetIt != assets.end())
|
||||
{
|
||||
// Set download state to SUCCESSED
|
||||
_tempManifest->setAssetDownloadState(customId, Manifest::DownloadState::SUCCESSED);
|
||||
|
||||
// Add file to need decompress list
|
||||
if (assetIt->second.compressed) {
|
||||
_compressedFiles.push_back(storagePath);
|
||||
}
|
||||
}
|
||||
|
||||
auto unitIt = _downloadUnits.find(customId);
|
||||
if (unitIt != _downloadUnits.end())
|
||||
{
|
||||
// Reduce count only when unit found in _downloadUnits
|
||||
_totalWaitToDownload--;
|
||||
|
||||
_percentByFile = 100 * (float)(_totalToDownload - _totalWaitToDownload) / _totalToDownload;
|
||||
// Notify progression event
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "");
|
||||
}
|
||||
// Notify asset updated event
|
||||
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::ASSET_UPDATED, customId);
|
||||
|
||||
unitIt = _failedUnits.find(customId);
|
||||
// Found unit and delete it
|
||||
if (unitIt != _failedUnits.end())
|
||||
{
|
||||
// Remove from failed units list
|
||||
_failedUnits.erase(unitIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerEx::destroyDownloadedVersion()
|
||||
{
|
||||
_fileUtils->removeFile(_cacheVersionPath);
|
||||
_fileUtils->removeFile(_cacheManifestPath);
|
||||
}
|
||||
|
||||
NS_CC_EXT_END
|
|
@ -0,0 +1,266 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2013 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __AssetsManagerEx__
|
||||
#define __AssetsManagerEx__
|
||||
|
||||
#include "base/CCEventDispatcher.h"
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "CCEventAssetsManagerEx.h"
|
||||
#include "Downloader.h"
|
||||
#include "Manifest.h"
|
||||
#include "extensions/ExtensionMacros.h"
|
||||
#include "extensions/ExtensionExport.h"
|
||||
#include "json/document.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
NS_CC_EXT_BEGIN
|
||||
|
||||
/**
|
||||
* @brief This class is used to auto update resources, such as pictures or scripts.
|
||||
*/
|
||||
class CC_EX_DLL AssetsManagerEx : public Ref
|
||||
{
|
||||
public:
|
||||
|
||||
friend class Downloader;
|
||||
friend int downloadProgressFunc(Downloader::ProgressData *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded);
|
||||
|
||||
//! Update states
|
||||
enum class State
|
||||
{
|
||||
UNCHECKED,
|
||||
PREDOWNLOAD_VERSION,
|
||||
DOWNLOADING_VERSION,
|
||||
VERSION_LOADED,
|
||||
PREDOWNLOAD_MANIFEST,
|
||||
DOWNLOADING_MANIFEST,
|
||||
MANIFEST_LOADED,
|
||||
NEED_UPDATE,
|
||||
UPDATING,
|
||||
UP_TO_DATE,
|
||||
FAIL_TO_UPDATE
|
||||
};
|
||||
|
||||
const static std::string VERSION_ID;
|
||||
const static std::string MANIFEST_ID;
|
||||
const static std::string BATCH_UPDATE_ID;
|
||||
|
||||
/** @brief Create function for creating a new AssetsManagerEx
|
||||
@param manifestUrl The url for the local manifest file
|
||||
@param storagePath The storage path for downloaded assetes
|
||||
@warning The cached manifest in your storage path have higher priority and will be searched first,
|
||||
only if it doesn't exist, AssetsManagerEx will use the given manifestUrl.
|
||||
*/
|
||||
static AssetsManagerEx* create(const std::string &manifestUrl, const std::string &storagePath);
|
||||
|
||||
/** @brief Check out if there is a new version of manifest.
|
||||
* You may use this method before updating, then let user determine whether
|
||||
* he wants to update resources.
|
||||
*/
|
||||
void checkUpdate();
|
||||
|
||||
/** @brief Update with the current local manifest.
|
||||
*/
|
||||
void update();
|
||||
|
||||
/** @brief Reupdate all failed assets under the current AssetsManagerEx context
|
||||
*/
|
||||
void downloadFailedAssets();
|
||||
|
||||
/** @brief Gets the current update state.
|
||||
*/
|
||||
State getState() const;
|
||||
|
||||
/** @brief Gets storage path.
|
||||
*/
|
||||
const std::string& getStoragePath() const;
|
||||
|
||||
/** @brief Function for retrieve the local manifest object
|
||||
*/
|
||||
const Manifest* getLocalManifest() const;
|
||||
|
||||
/** @brief Function for retrieve the remote manifest object
|
||||
*/
|
||||
const Manifest* getRemoteManifest() const;
|
||||
|
||||
CC_CONSTRUCTOR_ACCESS:
|
||||
|
||||
AssetsManagerEx(const std::string& manifestUrl, const std::string& storagePath);
|
||||
|
||||
virtual ~AssetsManagerEx();
|
||||
|
||||
protected:
|
||||
|
||||
std::string basename(const std::string& path) const;
|
||||
|
||||
std::string get(const std::string& key) const;
|
||||
|
||||
void loadLocalManifest(const std::string& manifestUrl);
|
||||
|
||||
void prepareLocalManifest();
|
||||
|
||||
void setStoragePath(const std::string& storagePath);
|
||||
|
||||
void adjustPath(std::string &path);
|
||||
|
||||
void dispatchUpdateEvent(EventAssetsManagerEx::EventCode code, const std::string &message = "", const std::string &assetId = "", int curle_code = 0, int curlm_code = 0);
|
||||
|
||||
void downloadVersion();
|
||||
void parseVersion();
|
||||
void downloadManifest();
|
||||
void parseManifest();
|
||||
void startUpdate();
|
||||
void updateSucceed();
|
||||
bool decompress(const std::string &filename);
|
||||
void decompressDownloadedZip();
|
||||
|
||||
/** @brief Update a list of assets under the current AssetsManagerEx context
|
||||
*/
|
||||
void updateAssets(const Downloader::DownloadUnits& assets);
|
||||
|
||||
/** @brief Retrieve all failed assets during the last update
|
||||
*/
|
||||
const Downloader::DownloadUnits& getFailedAssets() const;
|
||||
|
||||
/** @brief Function for destorying the downloaded version file and manifest file
|
||||
*/
|
||||
void destroyDownloadedVersion();
|
||||
|
||||
/** @brief Call back function for error handling,
|
||||
the error will then be reported to user's listener registed in addUpdateEventListener
|
||||
@param error The error object contains ErrorCode, message, asset url, asset key
|
||||
@warning AssetsManagerEx internal use only
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
virtual void onError(const Downloader::Error &error);
|
||||
|
||||
/** @brief Call back function for recording downloading percent of the current asset,
|
||||
the progression will then be reported to user's listener registed in addUpdateProgressEventListener
|
||||
@param total Total size to download for this asset
|
||||
@param downloaded Total size already downloaded for this asset
|
||||
@param url The url of this asset
|
||||
@param customId The key of this asset
|
||||
@warning AssetsManagerEx internal use only
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
virtual void onProgress(double total, double downloaded, const std::string &url, const std::string &customId);
|
||||
|
||||
/** @brief Call back function for success of the current asset
|
||||
the success event will then be send to user's listener registed in addUpdateEventListener
|
||||
@param srcUrl The url of this asset
|
||||
@param customId The key of this asset
|
||||
@warning AssetsManagerEx internal use only
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
virtual void onSuccess(const std::string &srcUrl, const std::string &storagePath, const std::string &customId);
|
||||
|
||||
private:
|
||||
|
||||
//! The event of the current AssetsManagerEx in event dispatcher
|
||||
std::string _eventName;
|
||||
|
||||
//! Reference to the global event dispatcher
|
||||
EventDispatcher *_eventDispatcher;
|
||||
//! Reference to the global file utils
|
||||
FileUtils *_fileUtils;
|
||||
|
||||
//! State of update
|
||||
State _updateState;
|
||||
|
||||
//! Downloader
|
||||
std::shared_ptr<Downloader> _downloader;
|
||||
|
||||
//! The reference to the local assets
|
||||
const std::unordered_map<std::string, Manifest::Asset> *_assets;
|
||||
|
||||
//! The path to store downloaded resources.
|
||||
std::string _storagePath;
|
||||
|
||||
//! The local path of cached version file
|
||||
std::string _cacheVersionPath;
|
||||
|
||||
//! The local path of cached manifest file
|
||||
std::string _cacheManifestPath;
|
||||
|
||||
//! The local path of cached temporary manifest file
|
||||
std::string _tempManifestPath;
|
||||
|
||||
//! The path of local manifest file
|
||||
std::string _manifestUrl;
|
||||
|
||||
//! Local manifest
|
||||
Manifest *_localManifest;
|
||||
|
||||
//! Local temporary manifest for download resuming
|
||||
Manifest *_tempManifest;
|
||||
|
||||
//! Remote manifest
|
||||
Manifest *_remoteManifest;
|
||||
|
||||
//! Whether user have requested to update
|
||||
bool _waitToUpdate;
|
||||
|
||||
//! All assets unit to download
|
||||
Downloader::DownloadUnits _downloadUnits;
|
||||
|
||||
//! All failed units
|
||||
Downloader::DownloadUnits _failedUnits;
|
||||
|
||||
//! All files to be decompressed
|
||||
std::vector<std::string> _compressedFiles;
|
||||
|
||||
//! Download percent
|
||||
float _percent;
|
||||
|
||||
//! Download percent by file
|
||||
float _percentByFile;
|
||||
|
||||
//! Indicate whether the total size should be enabled
|
||||
int _totalEnabled;
|
||||
|
||||
//! Indicate the number of file whose total size have been collected
|
||||
int _sizeCollected;
|
||||
|
||||
//! Total file size need to be downloaded (sum of all file)
|
||||
double _totalSize;
|
||||
|
||||
//! Downloaded size for each file
|
||||
std::unordered_map<std::string, double> _downloadedSize;
|
||||
|
||||
//! Total number of assets to download
|
||||
int _totalToDownload;
|
||||
//! Total number of assets still waiting to be downloaded
|
||||
int _totalWaitToDownload;
|
||||
};
|
||||
|
||||
NS_CC_EXT_END
|
||||
|
||||
#endif /* defined(__AssetsManagerEx__) */
|
|
@ -0,0 +1,46 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "CCEventAssetsManagerEx.h"
|
||||
#include "base/ccMacros.h"
|
||||
#include <functional>
|
||||
#include "AssetsManagerEx.h"
|
||||
|
||||
NS_CC_EXT_BEGIN
|
||||
|
||||
EventAssetsManagerEx::EventAssetsManagerEx(const std::string& eventName, cocos2d::extension::AssetsManagerEx *manager, const EventCode &code, float percent/* = 0 */, float percentByFile/* = 0*/, const std::string& assetId/* = "" */, const std::string& message/* = "" */, int curle_code/* = CURLE_OK*/, int curlm_code/* = CURLM_OK*/)
|
||||
: EventCustom(eventName)
|
||||
, _manager(manager)
|
||||
, _code(code)
|
||||
, _curle_code(curle_code)
|
||||
, _curlm_code(curlm_code)
|
||||
, _percent(percent)
|
||||
, _percentByFile(percentByFile)
|
||||
, _assetId(assetId)
|
||||
, _message(message)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
NS_CC_EXT_END
|
|
@ -0,0 +1,99 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __cocos2d_libs__CCEventAssetsManagerEx__
|
||||
#define __cocos2d_libs__CCEventAssetsManagerEx__
|
||||
|
||||
#include "base/CCEvent.h"
|
||||
#include "base/CCEventCustom.h"
|
||||
#include "extensions/ExtensionMacros.h"
|
||||
#include "extensions/ExtensionExport.h"
|
||||
|
||||
NS_CC_EXT_BEGIN
|
||||
|
||||
class AssetsManagerEx;
|
||||
|
||||
class CC_EX_DLL EventAssetsManagerEx : public cocos2d::EventCustom
|
||||
{
|
||||
public:
|
||||
|
||||
friend class AssetsManagerEx;
|
||||
|
||||
//! Update events code
|
||||
enum class EventCode
|
||||
{
|
||||
ERROR_NO_LOCAL_MANIFEST,
|
||||
ERROR_DOWNLOAD_MANIFEST,
|
||||
ERROR_PARSE_MANIFEST,
|
||||
NEW_VERSION_FOUND,
|
||||
ALREADY_UP_TO_DATE,
|
||||
UPDATE_PROGRESSION,
|
||||
ASSET_UPDATED,
|
||||
ERROR_UPDATING,
|
||||
UPDATE_FINISHED,
|
||||
UPDATE_FAILED,
|
||||
ERROR_DECOMPRESS
|
||||
};
|
||||
|
||||
inline EventCode getEventCode() const { return _code; };
|
||||
|
||||
inline int getCURLECode() const { return _curle_code; };
|
||||
|
||||
inline int getCURLMCode() const { return _curlm_code; };
|
||||
|
||||
inline std::string getMessage() const { return _message; };
|
||||
|
||||
inline std::string getAssetId() const { return _assetId; };
|
||||
|
||||
inline cocos2d::extension::AssetsManagerEx *getAssetsManagerEx() const { return _manager; };
|
||||
|
||||
inline float getPercent() const { return _percent; };
|
||||
|
||||
inline float getPercentByFile() const { return _percentByFile; };
|
||||
|
||||
CC_CONSTRUCTOR_ACCESS:
|
||||
/** Constructor */
|
||||
EventAssetsManagerEx(const std::string& eventName, cocos2d::extension::AssetsManagerEx *manager, const EventCode &code, float percent = 0, float percentByFile = 0, const std::string& assetId = "", const std::string& message = "", int curle_code = 0, int curlm_code = 0);
|
||||
|
||||
private:
|
||||
EventCode _code;
|
||||
|
||||
cocos2d::extension::AssetsManagerEx *_manager;
|
||||
|
||||
std::string _message;
|
||||
|
||||
std::string _assetId;
|
||||
|
||||
int _curle_code;
|
||||
|
||||
int _curlm_code;
|
||||
|
||||
float _percent;
|
||||
|
||||
float _percentByFile;
|
||||
};
|
||||
|
||||
NS_CC_EXT_END
|
||||
|
||||
#endif /* defined(__cocos2d_libs__CCEventAssetsManagerEx__) */
|
|
@ -0,0 +1,98 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "CCEventListenerAssetsManagerEx.h"
|
||||
#include "CCEventAssetsManagerEx.h"
|
||||
#include "AssetsManagerEx.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_CC_EXT_BEGIN
|
||||
|
||||
const std::string EventListenerAssetsManagerEx::LISTENER_ID = "__cc_assets_manager_";
|
||||
|
||||
EventListenerAssetsManagerEx::EventListenerAssetsManagerEx()
|
||||
: _onAssetsManagerExEvent(nullptr)
|
||||
, _AssetsManagerEx(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
EventListenerAssetsManagerEx* EventListenerAssetsManagerEx::create(cocos2d::extension::AssetsManagerEx *AssetsManagerEx, const std::function<void(EventAssetsManagerEx*)>& callback)
|
||||
{
|
||||
EventListenerAssetsManagerEx* ret = new EventListenerAssetsManagerEx();
|
||||
if (ret && ret->init(AssetsManagerEx, callback))
|
||||
{
|
||||
ret->autorelease();
|
||||
}
|
||||
else
|
||||
{
|
||||
CC_SAFE_DELETE(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool EventListenerAssetsManagerEx::init(const AssetsManagerEx *AssetsManagerEx, const std::function<void(EventAssetsManagerEx*)>& callback)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
_AssetsManagerEx = AssetsManagerEx;
|
||||
_onAssetsManagerExEvent = callback;
|
||||
|
||||
auto func = [this](EventCustom *event) -> void
|
||||
{
|
||||
EventAssetsManagerEx *eventAssetsManagerEx = dynamic_cast<EventAssetsManagerEx*>(event);
|
||||
_onAssetsManagerExEvent(eventAssetsManagerEx);
|
||||
};
|
||||
std::string pointer = StringUtils::format("%p", AssetsManagerEx);
|
||||
if (EventListenerCustom::init(LISTENER_ID + pointer, func))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
EventListenerAssetsManagerEx* EventListenerAssetsManagerEx::clone()
|
||||
{
|
||||
EventListenerAssetsManagerEx* ret = new EventListenerAssetsManagerEx();
|
||||
if (ret && ret->init(_AssetsManagerEx, _onAssetsManagerExEvent))
|
||||
{
|
||||
ret->autorelease();
|
||||
}
|
||||
else
|
||||
{
|
||||
CC_SAFE_DELETE(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool EventListenerAssetsManagerEx::checkAvailable()
|
||||
{
|
||||
bool ret = false;
|
||||
if (EventListener::checkAvailable() && _AssetsManagerEx != nullptr && _onAssetsManagerExEvent != nullptr)
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
NS_CC_EXT_END
|
|
@ -0,0 +1,86 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __cocos2d_libs__CCEventListenerAssetsManagerEx__
|
||||
#define __cocos2d_libs__CCEventListenerAssetsManagerEx__
|
||||
|
||||
#include "base/CCEventListener.h"
|
||||
#include "base/CCEventListenerCustom.h"
|
||||
#include "extensions/ExtensionMacros.h"
|
||||
#include "extensions/ExtensionExport.h"
|
||||
|
||||
NS_CC_EXT_BEGIN
|
||||
|
||||
class EventAssetsManagerEx;
|
||||
class AssetsManagerEx;
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* auto dispatcher = Director::getInstance()->getEventDispatcher();
|
||||
* auto manager = AssetsManagerEx::create(manifestUrl, storagePath);
|
||||
* Adds a listener:
|
||||
*
|
||||
* auto callback = [](EventAssetsManagerEx* event){ do_some_thing(); };
|
||||
* auto listener = EventListenerAssetsManagerEx::create(manager, callback);
|
||||
* dispatcher->addEventListenerWithSceneGraphPriority(listener, one_node);
|
||||
*
|
||||
* Removes a listener
|
||||
*
|
||||
* dispatcher->removeEventListener(listener);
|
||||
*/
|
||||
class CC_EX_DLL EventListenerAssetsManagerEx : public cocos2d::EventListenerCustom
|
||||
{
|
||||
public:
|
||||
friend class AssetsManagerEx;
|
||||
|
||||
/** Creates an event listener with type and callback.
|
||||
* @param eventType The type of the event.
|
||||
* @param callback The callback function when the specified event was emitted.
|
||||
*/
|
||||
static EventListenerAssetsManagerEx* create(AssetsManagerEx *AssetsManagerEx, const std::function<void(EventAssetsManagerEx*)>& callback);
|
||||
|
||||
/// Overrides
|
||||
virtual bool checkAvailable() override;
|
||||
virtual EventListenerAssetsManagerEx* clone() override;
|
||||
|
||||
CC_CONSTRUCTOR_ACCESS:
|
||||
/** Constructor */
|
||||
EventListenerAssetsManagerEx();
|
||||
|
||||
/** Initializes event with type and callback function */
|
||||
bool init(const AssetsManagerEx *AssetsManagerEx, const std::function<void(EventAssetsManagerEx*)>& callback);
|
||||
|
||||
protected:
|
||||
static const std::string LISTENER_ID;
|
||||
|
||||
std::function<void(EventAssetsManagerEx*)> _onAssetsManagerExEvent;
|
||||
|
||||
const AssetsManagerEx *_AssetsManagerEx;
|
||||
|
||||
//friend class luaEventListenerAssetsManagerEx;
|
||||
};
|
||||
|
||||
NS_CC_EXT_END
|
||||
|
||||
#endif /* defined(__cocos2d_libs__CCEventListenerAssetsManagerEx__) */
|
|
@ -0,0 +1,680 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2013 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "Downloader.h"
|
||||
#include "cocos2d.h"
|
||||
#include <curl/curl.h>
|
||||
#include <curl/easy.h>
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
|
||||
NS_CC_EXT_BEGIN
|
||||
|
||||
#define LOW_SPEED_LIMIT 1L
|
||||
#define LOW_SPEED_TIME 5L
|
||||
#define MAX_REDIRS 2
|
||||
#define DEFAULT_TIMEOUT 5
|
||||
#define HTTP_CODE_SUPPORT_RESUME 206
|
||||
|
||||
#define TEMP_EXT ".temp"
|
||||
|
||||
size_t fileWriteFunc(void *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
{
|
||||
FILE *fp = (FILE*)userdata;
|
||||
size_t written = fwrite(ptr, size, nmemb, fp);
|
||||
return written;
|
||||
}
|
||||
|
||||
size_t bufferWriteFunc(void *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
{
|
||||
Downloader::StreamData *streamBuffer = (Downloader::StreamData *)userdata;
|
||||
size_t written = size * nmemb;
|
||||
// Avoid pointer overflow
|
||||
if (streamBuffer->offset + written <= streamBuffer->total)
|
||||
{
|
||||
memcpy(streamBuffer->buffer + streamBuffer->offset, ptr, written);
|
||||
streamBuffer->offset += written;
|
||||
return written;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
// This is only for batchDownload process, will notify file succeed event in progress function
|
||||
int batchDownloadProgressFunc(Downloader::ProgressData *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
|
||||
{
|
||||
if (ptr->totalToDownload == 0)
|
||||
{
|
||||
ptr->totalToDownload = totalToDownload;
|
||||
}
|
||||
|
||||
if (ptr->downloaded != nowDownloaded)
|
||||
{
|
||||
ptr->downloaded = nowDownloaded;
|
||||
|
||||
Downloader::ProgressData data = *ptr;
|
||||
|
||||
if (nowDownloaded == totalToDownload)
|
||||
{
|
||||
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=]{
|
||||
if (!data.downloader.expired())
|
||||
{
|
||||
std::shared_ptr<Downloader> downloader = data.downloader.lock();
|
||||
|
||||
auto progressCB = downloader->getProgressCallback();
|
||||
if (progressCB != nullptr)
|
||||
{
|
||||
progressCB(totalToDownload, nowDownloaded, data.url, data.customId);
|
||||
}
|
||||
auto successCB = downloader->getSuccessCallback();
|
||||
if (successCB != nullptr)
|
||||
{
|
||||
successCB(data.url, data.path + data.name, data.customId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=]{
|
||||
if (!data.downloader.expired())
|
||||
{
|
||||
std::shared_ptr<Downloader> downloader = data.downloader.lock();
|
||||
|
||||
auto callback = downloader->getProgressCallback();
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback(totalToDownload, nowDownloaded, data.url, data.customId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Compare to batchDownloadProgressFunc, this only handles progress information notification
|
||||
int downloadProgressFunc(Downloader::ProgressData *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
|
||||
{
|
||||
if (ptr->totalToDownload == 0)
|
||||
{
|
||||
ptr->totalToDownload = totalToDownload;
|
||||
}
|
||||
|
||||
if (ptr->downloaded != nowDownloaded)
|
||||
{
|
||||
ptr->downloaded = nowDownloaded;
|
||||
Downloader::ProgressData data = *ptr;
|
||||
|
||||
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=]{
|
||||
if (!data.downloader.expired())
|
||||
{
|
||||
std::shared_ptr<Downloader> downloader = data.downloader.lock();
|
||||
|
||||
auto callback = downloader->getProgressCallback();
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback(totalToDownload, nowDownloaded, data.url, data.customId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Downloader::Downloader()
|
||||
: _onError(nullptr)
|
||||
, _onProgress(nullptr)
|
||||
, _onSuccess(nullptr)
|
||||
, _connectionTimeout(DEFAULT_TIMEOUT)
|
||||
, _supportResuming(false)
|
||||
{
|
||||
_fileUtils = FileUtils::getInstance();
|
||||
}
|
||||
|
||||
Downloader::~Downloader()
|
||||
{
|
||||
}
|
||||
|
||||
int Downloader::getConnectionTimeout()
|
||||
{
|
||||
return _connectionTimeout;
|
||||
}
|
||||
|
||||
void Downloader::setConnectionTimeout(int timeout)
|
||||
{
|
||||
if (timeout >= 0)
|
||||
_connectionTimeout = timeout;
|
||||
}
|
||||
|
||||
void Downloader::notifyError(ErrorCode code, const std::string &msg/* ="" */, const std::string &customId/* ="" */, int curle_code/* = CURLE_OK*/, int curlm_code/* = CURLM_OK*/)
|
||||
{
|
||||
std::weak_ptr<Downloader> ptr = shared_from_this();
|
||||
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=]{
|
||||
if (!ptr.expired())
|
||||
{
|
||||
std::shared_ptr<Downloader> downloader = ptr.lock();
|
||||
if (downloader->_onError != nullptr)
|
||||
{
|
||||
Error err;
|
||||
err.code = code;
|
||||
err.curle_code = curle_code;
|
||||
err.curlm_code = curlm_code;
|
||||
err.message = msg;
|
||||
err.customId = customId;
|
||||
downloader->_onError(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Downloader::notifyError(const std::string &msg, int curlm_code, const std::string &customId/* = ""*/)
|
||||
{
|
||||
notifyError(ErrorCode::CURL_MULTI_ERROR, msg, customId, CURLE_OK, curlm_code);
|
||||
}
|
||||
|
||||
void Downloader::notifyError(const std::string &msg, const std::string &customId, int curle_code)
|
||||
{
|
||||
notifyError(ErrorCode::CURL_EASY_ERROR, msg, customId, curle_code);
|
||||
}
|
||||
|
||||
std::string Downloader::getFileNameFromUrl(const std::string &srcUrl)
|
||||
{
|
||||
// Find file name and file extension
|
||||
std::string filename;
|
||||
unsigned long found = srcUrl.find_last_of("/\\");
|
||||
if (found != std::string::npos)
|
||||
filename = srcUrl.substr(found+1);
|
||||
return filename;
|
||||
}
|
||||
|
||||
void Downloader::clearBatchDownloadData()
|
||||
{
|
||||
while (_progDatas.size() != 0) {
|
||||
delete _progDatas.back();
|
||||
_progDatas.pop_back();
|
||||
}
|
||||
|
||||
while (_files.size() != 0) {
|
||||
delete _files.back();
|
||||
_files.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void Downloader::prepareDownload(const std::string &srcUrl, const std::string &storagePath, const std::string &customId, bool resumeDownload, FileDescriptor *fDesc, ProgressData *pData)
|
||||
{
|
||||
std::shared_ptr<Downloader> downloader = shared_from_this();
|
||||
pData->customId = customId;
|
||||
pData->url = srcUrl;
|
||||
pData->downloader = downloader;
|
||||
pData->downloaded = 0;
|
||||
pData->totalToDownload = 0;
|
||||
|
||||
fDesc->fp = nullptr;
|
||||
fDesc->curl = nullptr;
|
||||
|
||||
Error err;
|
||||
err.customId = customId;
|
||||
|
||||
// Asserts
|
||||
// Find file name and file extension
|
||||
unsigned long found = storagePath.find_last_of("/\\");
|
||||
if (found != std::string::npos)
|
||||
{
|
||||
pData->name = storagePath.substr(found+1);
|
||||
pData->path = storagePath.substr(0, found+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
err.code = ErrorCode::INVALID_URL;
|
||||
err.message = "Invalid url or filename not exist error: " + srcUrl;
|
||||
if (this->_onError) this->_onError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a file to save file.
|
||||
const std::string outFileName = storagePath + TEMP_EXT;
|
||||
if (_supportResuming && resumeDownload && _fileUtils->isFileExist(outFileName))
|
||||
{
|
||||
fDesc->fp = fopen(outFileName.c_str(), "ab");
|
||||
}
|
||||
else
|
||||
{
|
||||
fDesc->fp = fopen(outFileName.c_str(), "wb");
|
||||
}
|
||||
if (!fDesc->fp)
|
||||
{
|
||||
err.code = ErrorCode::CREATE_FILE;
|
||||
err.message = StringUtils::format("Can not create file %s: errno %d", outFileName.c_str(), errno);
|
||||
if (this->_onError) this->_onError(err);
|
||||
}
|
||||
}
|
||||
|
||||
bool Downloader::prepareHeader(void *curl, const std::string &srcUrl) const
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_URL, srcUrl.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
|
||||
if (curl_easy_perform(curl) == CURLE_OK)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
long Downloader::getContentSize(const std::string &srcUrl) const
|
||||
{
|
||||
double contentLength = -1;
|
||||
CURL *header = curl_easy_init();
|
||||
if (prepareHeader(header, srcUrl))
|
||||
{
|
||||
curl_easy_getinfo(header, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength);
|
||||
}
|
||||
curl_easy_cleanup(header);
|
||||
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
void Downloader::downloadToBufferAsync(const std::string &srcUrl, unsigned char *buffer, const long &size, const std::string &customId/* = ""*/)
|
||||
{
|
||||
if (buffer != nullptr)
|
||||
{
|
||||
std::shared_ptr<Downloader> downloader = shared_from_this();
|
||||
ProgressData pData;
|
||||
pData.customId = customId;
|
||||
pData.url = srcUrl;
|
||||
pData.downloader = downloader;
|
||||
pData.downloaded = 0;
|
||||
pData.totalToDownload = 0;
|
||||
|
||||
StreamData streamBuffer;
|
||||
streamBuffer.buffer = buffer;
|
||||
streamBuffer.total = size;
|
||||
streamBuffer.offset = 0;
|
||||
|
||||
auto t = std::thread(&Downloader::downloadToBuffer, this, srcUrl, customId, streamBuffer, pData);
|
||||
t.detach();
|
||||
}
|
||||
}
|
||||
|
||||
void Downloader::downloadToBufferSync(const std::string &srcUrl, unsigned char *buffer, const long &size, const std::string &customId/* = ""*/)
|
||||
{
|
||||
if (buffer != nullptr)
|
||||
{
|
||||
std::shared_ptr<Downloader> downloader = shared_from_this();
|
||||
ProgressData pData;
|
||||
pData.customId = customId;
|
||||
pData.url = srcUrl;
|
||||
pData.downloader = downloader;
|
||||
pData.downloaded = 0;
|
||||
pData.totalToDownload = 0;
|
||||
|
||||
StreamData streamBuffer;
|
||||
streamBuffer.buffer = buffer;
|
||||
streamBuffer.total = size;
|
||||
streamBuffer.offset = 0;
|
||||
|
||||
downloadToBuffer(srcUrl, customId, streamBuffer, pData);
|
||||
}
|
||||
}
|
||||
|
||||
void Downloader::downloadToBuffer(const std::string &srcUrl, const std::string &customId, const StreamData &buffer, const ProgressData &data)
|
||||
{
|
||||
std::weak_ptr<Downloader> ptr = shared_from_this();
|
||||
CURL *curl = curl_easy_init();
|
||||
if (!curl)
|
||||
{
|
||||
this->notifyError(ErrorCode::CURL_EASY_ERROR, "Can not init curl with curl_easy_init", customId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Download pacakge
|
||||
curl_easy_setopt(curl, CURLOPT_URL, srcUrl.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, bufferWriteFunc);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, downloadProgressFunc);
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &data);
|
||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
|
||||
if (_connectionTimeout) curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, _connectionTimeout);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, LOW_SPEED_LIMIT);
|
||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, LOW_SPEED_TIME);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK)
|
||||
{
|
||||
_fileUtils->removeFile(data.path + data.name + TEMP_EXT);
|
||||
std::string msg = StringUtils::format("Unable to download file: [curl error]%s", curl_easy_strerror(res));
|
||||
this->notifyError(msg, customId, res);
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=]{
|
||||
if (!ptr.expired())
|
||||
{
|
||||
std::shared_ptr<Downloader> downloader = ptr.lock();
|
||||
|
||||
auto successCB = downloader->getSuccessCallback();
|
||||
if (successCB != nullptr)
|
||||
{
|
||||
successCB(data.url, "", data.customId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Downloader::downloadAsync(const std::string &srcUrl, const std::string &storagePath, const std::string &customId/* = ""*/)
|
||||
{
|
||||
FileDescriptor fDesc;
|
||||
ProgressData pData;
|
||||
prepareDownload(srcUrl, storagePath, customId, false, &fDesc, &pData);
|
||||
if (fDesc.fp != NULL)
|
||||
{
|
||||
auto t = std::thread(&Downloader::download, this, srcUrl, customId, fDesc, pData);
|
||||
t.detach();
|
||||
}
|
||||
}
|
||||
|
||||
void Downloader::downloadSync(const std::string &srcUrl, const std::string &storagePath, const std::string &customId/* = ""*/)
|
||||
{
|
||||
FileDescriptor fDesc;
|
||||
ProgressData pData;
|
||||
prepareDownload(srcUrl, storagePath, customId, false, &fDesc, &pData);
|
||||
if (fDesc.fp != NULL)
|
||||
{
|
||||
download(srcUrl, customId, fDesc, pData);
|
||||
}
|
||||
}
|
||||
|
||||
void Downloader::download(const std::string &srcUrl, const std::string &customId, const FileDescriptor &fDesc, const ProgressData &data)
|
||||
{
|
||||
std::weak_ptr<Downloader> ptr = shared_from_this();
|
||||
CURL *curl = curl_easy_init();
|
||||
if (!curl)
|
||||
{
|
||||
this->notifyError(ErrorCode::CURL_EASY_ERROR, "Can not init curl with curl_easy_init", customId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Download pacakge
|
||||
curl_easy_setopt(curl, CURLOPT_URL, srcUrl.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fileWriteFunc);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fDesc.fp);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, downloadProgressFunc);
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &data);
|
||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
|
||||
if (_connectionTimeout) curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, _connectionTimeout);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, LOW_SPEED_LIMIT);
|
||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, LOW_SPEED_TIME);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK)
|
||||
{
|
||||
_fileUtils->removeFile(data.path + data.name + TEMP_EXT);
|
||||
std::string msg = StringUtils::format("Unable to download file: [curl error]%s", curl_easy_strerror(res));
|
||||
this->notifyError(msg, customId, res);
|
||||
}
|
||||
|
||||
fclose(fDesc.fp);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
// This can only be done after fclose
|
||||
if (res == CURLE_OK)
|
||||
{
|
||||
_fileUtils->renameFile(data.path, data.name + TEMP_EXT, data.name);
|
||||
}
|
||||
|
||||
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=]{
|
||||
if (!ptr.expired())
|
||||
{
|
||||
std::shared_ptr<Downloader> downloader = ptr.lock();
|
||||
|
||||
auto successCB = downloader->getSuccessCallback();
|
||||
if (successCB != nullptr)
|
||||
{
|
||||
successCB(data.url, data.path + data.name, data.customId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Downloader::batchDownloadAsync(const DownloadUnits &units, const std::string &batchId/* = ""*/)
|
||||
{
|
||||
auto t = std::thread(&Downloader::batchDownloadSync, this, units, batchId);
|
||||
t.detach();
|
||||
}
|
||||
|
||||
void Downloader::batchDownloadSync(const DownloadUnits &units, const std::string &batchId/* = ""*/)
|
||||
{
|
||||
if (units.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Make sure downloader won't be released
|
||||
std::weak_ptr<Downloader> ptr = shared_from_this();
|
||||
|
||||
// Test server download resuming support with the first unit
|
||||
_supportResuming = false;
|
||||
CURL *header = curl_easy_init();
|
||||
// Make a resume request
|
||||
curl_easy_setopt(header, CURLOPT_RESUME_FROM_LARGE, 0);
|
||||
if (prepareHeader(header, units.begin()->second.srcUrl))
|
||||
{
|
||||
long responseCode;
|
||||
curl_easy_getinfo(header, CURLINFO_RESPONSE_CODE, &responseCode);
|
||||
if (responseCode == HTTP_CODE_SUPPORT_RESUME)
|
||||
{
|
||||
_supportResuming = true;
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(header);
|
||||
|
||||
int count = 0;
|
||||
DownloadUnits group;
|
||||
for (auto it = units.cbegin(); it != units.cend(); ++it, ++count)
|
||||
{
|
||||
if (count == FOPEN_MAX)
|
||||
{
|
||||
groupBatchDownload(group);
|
||||
group.clear();
|
||||
count = 0;
|
||||
}
|
||||
const std::string &key = it->first;
|
||||
const DownloadUnit &unit = it->second;
|
||||
group.emplace(key, unit);
|
||||
}
|
||||
if (group.size() > 0)
|
||||
{
|
||||
groupBatchDownload(group);
|
||||
}
|
||||
|
||||
Director::getInstance()->getScheduler()->performFunctionInCocosThread([ptr, batchId]{
|
||||
if (!ptr.expired()) {
|
||||
std::shared_ptr<Downloader> downloader = ptr.lock();
|
||||
auto callback = downloader->getSuccessCallback();
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback("", "", batchId);
|
||||
}
|
||||
}
|
||||
});
|
||||
_supportResuming = false;
|
||||
}
|
||||
|
||||
void Downloader::groupBatchDownload(const DownloadUnits &units)
|
||||
{
|
||||
CURLM* multi_handle = curl_multi_init();
|
||||
int still_running = 0;
|
||||
|
||||
for (auto it = units.cbegin(); it != units.cend(); ++it)
|
||||
{
|
||||
DownloadUnit unit = it->second;
|
||||
std::string srcUrl = unit.srcUrl;
|
||||
std::string storagePath = unit.storagePath;
|
||||
std::string customId = unit.customId;
|
||||
|
||||
FileDescriptor *fDesc = new FileDescriptor();
|
||||
ProgressData *data = new ProgressData();
|
||||
prepareDownload(srcUrl, storagePath, customId, unit.resumeDownload, fDesc, data);
|
||||
|
||||
if (fDesc->fp != NULL)
|
||||
{
|
||||
CURL* curl = curl_easy_init();
|
||||
curl_easy_setopt(curl, CURLOPT_URL, srcUrl.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fileWriteFunc);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fDesc->fp);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, batchDownloadProgressFunc);
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, data);
|
||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
|
||||
if (_connectionTimeout) curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, _connectionTimeout);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, LOW_SPEED_LIMIT);
|
||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, LOW_SPEED_TIME);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, MAX_REDIRS);
|
||||
|
||||
// Resuming download support
|
||||
if (_supportResuming && unit.resumeDownload)
|
||||
{
|
||||
// Check already downloaded size for current download unit
|
||||
long size = _fileUtils->getFileSize(storagePath + TEMP_EXT);
|
||||
if (size != -1)
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, size);
|
||||
}
|
||||
}
|
||||
fDesc->curl = curl;
|
||||
|
||||
CURLMcode code = curl_multi_add_handle(multi_handle, curl);
|
||||
if (code != CURLM_OK)
|
||||
{
|
||||
// Avoid memory leak
|
||||
fclose(fDesc->fp);
|
||||
delete data;
|
||||
delete fDesc;
|
||||
std::string msg = StringUtils::format("Unable to add curl handler for %s: [curl error]%s", customId.c_str(), curl_multi_strerror(code));
|
||||
this->notifyError(msg, code, customId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add to list for tracking
|
||||
_progDatas.push_back(data);
|
||||
_files.push_back(fDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Query multi perform
|
||||
CURLMcode curlm_code = CURLM_CALL_MULTI_PERFORM;
|
||||
while(CURLM_CALL_MULTI_PERFORM == curlm_code) {
|
||||
curlm_code = curl_multi_perform(multi_handle, &still_running);
|
||||
}
|
||||
if (curlm_code != CURLM_OK) {
|
||||
std::string msg = StringUtils::format("Unable to continue the download process: [curl error]%s", curl_multi_strerror(curlm_code));
|
||||
this->notifyError(msg, curlm_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool failed = false;
|
||||
while (still_running > 0 && !failed)
|
||||
{
|
||||
// set a suitable timeout to play around with
|
||||
struct timeval select_tv;
|
||||
long curl_timeo = -1;
|
||||
select_tv.tv_sec = 1;
|
||||
select_tv.tv_usec = 0;
|
||||
|
||||
curl_multi_timeout(multi_handle, &curl_timeo);
|
||||
if(curl_timeo >= 0) {
|
||||
select_tv.tv_sec = curl_timeo / 1000;
|
||||
if(select_tv.tv_sec > 1)
|
||||
select_tv.tv_sec = 1;
|
||||
else
|
||||
select_tv.tv_usec = (curl_timeo % 1000) * 1000;
|
||||
}
|
||||
|
||||
int rc;
|
||||
fd_set fdread;
|
||||
fd_set fdwrite;
|
||||
fd_set fdexcep;
|
||||
int maxfd = -1;
|
||||
FD_ZERO(&fdread);
|
||||
FD_ZERO(&fdwrite);
|
||||
FD_ZERO(&fdexcep);
|
||||
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
|
||||
rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &select_tv);
|
||||
|
||||
switch(rc)
|
||||
{
|
||||
case -1:
|
||||
failed = true;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
curlm_code = CURLM_CALL_MULTI_PERFORM;
|
||||
while(CURLM_CALL_MULTI_PERFORM == curlm_code) {
|
||||
curlm_code = curl_multi_perform(multi_handle, &still_running);
|
||||
}
|
||||
if (curlm_code != CURLM_OK) {
|
||||
std::string msg = StringUtils::format("Unable to continue the download process: [curl error]%s", curl_multi_strerror(curlm_code));
|
||||
this->notifyError(msg, curlm_code);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up and close files
|
||||
curl_multi_cleanup(multi_handle);
|
||||
for (auto it = _files.begin(); it != _files.end(); ++it)
|
||||
{
|
||||
FILE *f = (*it)->fp;
|
||||
fclose(f);
|
||||
auto single = (*it)->curl;
|
||||
curl_multi_remove_handle(multi_handle, single);
|
||||
curl_easy_cleanup(single);
|
||||
}
|
||||
|
||||
// Check unfinished files and notify errors, succeed files will be renamed from temporary file name to real name
|
||||
for (auto it = _progDatas.begin(); it != _progDatas.end(); ++it) {
|
||||
ProgressData *data = *it;
|
||||
if (data->downloaded < data->totalToDownload || data->totalToDownload == 0)
|
||||
{
|
||||
this->notifyError(ErrorCode::NETWORK, "Unable to download file", data->customId);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fileUtils->renameFile(data->path, data->name + TEMP_EXT, data->name);
|
||||
}
|
||||
}
|
||||
|
||||
clearBatchDownloadData();
|
||||
}
|
||||
|
||||
NS_CC_EXT_END
|
|
@ -0,0 +1,196 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2013 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __Downloader__
|
||||
#define __Downloader__
|
||||
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "extensions/ExtensionMacros.h"
|
||||
#include "extensions/ExtensionExport.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
NS_CC_EXT_BEGIN
|
||||
|
||||
class CC_EX_DLL Downloader : public std::enable_shared_from_this<Downloader>
|
||||
{
|
||||
public:
|
||||
|
||||
friend class AssetsManagerEx;
|
||||
|
||||
enum class ErrorCode
|
||||
{
|
||||
CREATE_FILE,
|
||||
|
||||
NETWORK,
|
||||
|
||||
NO_NEW_VERSION,
|
||||
|
||||
UNCOMPRESS,
|
||||
|
||||
CURL_UNINIT,
|
||||
|
||||
CURL_MULTI_ERROR,
|
||||
|
||||
CURL_EASY_ERROR,
|
||||
|
||||
INVALID_URL,
|
||||
|
||||
INVALID_STORAGE_PATH
|
||||
};
|
||||
|
||||
struct Error
|
||||
{
|
||||
ErrorCode code;
|
||||
int curlm_code;
|
||||
int curle_code;
|
||||
std::string message;
|
||||
std::string customId;
|
||||
std::string url;
|
||||
};
|
||||
|
||||
struct ProgressData
|
||||
{
|
||||
std::weak_ptr<Downloader> downloader;
|
||||
std::string customId;
|
||||
std::string url;
|
||||
std::string path;
|
||||
std::string name;
|
||||
double downloaded;
|
||||
double totalToDownload;
|
||||
};
|
||||
|
||||
struct DownloadUnit
|
||||
{
|
||||
std::string srcUrl;
|
||||
std::string storagePath;
|
||||
std::string customId;
|
||||
bool resumeDownload;
|
||||
};
|
||||
|
||||
struct StreamData
|
||||
{
|
||||
long offset;
|
||||
long total;
|
||||
unsigned char *buffer;
|
||||
};
|
||||
|
||||
typedef std::unordered_map<std::string, DownloadUnit> DownloadUnits;
|
||||
|
||||
typedef std::function<void(const Downloader::Error &)> ErrorCallback;
|
||||
typedef std::function<void(double, double, const std::string &, const std::string &)> ProgressCallback;
|
||||
typedef std::function<void(const std::string &, const std::string &, const std::string &)> SuccessCallback;
|
||||
|
||||
int getConnectionTimeout();
|
||||
|
||||
void setConnectionTimeout(int timeout);
|
||||
|
||||
void setErrorCallback(const ErrorCallback &callback) { _onError = callback; };
|
||||
|
||||
void setProgressCallback(const ProgressCallback &callback) { _onProgress = callback; };
|
||||
|
||||
void setSuccessCallback(const SuccessCallback &callback) { _onSuccess = callback; };
|
||||
|
||||
ErrorCallback getErrorCallback() const { return _onError; };
|
||||
|
||||
ProgressCallback getProgressCallback() const { return _onProgress; };
|
||||
|
||||
SuccessCallback getSuccessCallback() const { return _onSuccess; };
|
||||
|
||||
long getContentSize(const std::string &srcUrl) const;
|
||||
|
||||
void downloadToBufferAsync(const std::string &srcUrl, unsigned char *buffer, const long &size, const std::string &customId = "");
|
||||
|
||||
void downloadToBufferSync(const std::string &srcUrl, unsigned char *buffer, const long &size, const std::string &customId = "");
|
||||
|
||||
void downloadAsync(const std::string &srcUrl, const std::string &storagePath, const std::string &customId = "");
|
||||
|
||||
void downloadSync(const std::string &srcUrl, const std::string &storagePath, const std::string &customId = "");
|
||||
|
||||
void batchDownloadAsync(const DownloadUnits &units, const std::string &batchId = "");
|
||||
|
||||
void batchDownloadSync(const DownloadUnits &units, const std::string &batchId = "");
|
||||
|
||||
/**
|
||||
* The default constructor.
|
||||
*/
|
||||
Downloader();
|
||||
|
||||
~Downloader();
|
||||
|
||||
protected:
|
||||
|
||||
struct FileDescriptor
|
||||
{
|
||||
FILE *fp;
|
||||
void *curl;
|
||||
};
|
||||
|
||||
void prepareDownload(const std::string &srcUrl, const std::string &storagePath, const std::string &customId, bool resumeDownload, FileDescriptor *fDesc, ProgressData *pData);
|
||||
|
||||
bool prepareHeader(void *curl, const std::string &srcUrl) const;
|
||||
|
||||
void downloadToBuffer(const std::string &srcUrl, const std::string &customId, const StreamData &buffer, const ProgressData &data);
|
||||
|
||||
void download(const std::string &srcUrl, const std::string &customId, const FileDescriptor &fDesc, const ProgressData &data);
|
||||
|
||||
void groupBatchDownload(const DownloadUnits &units);
|
||||
|
||||
void notifyError(ErrorCode code, const std::string &msg = "", const std::string &customId = "", int curle_code = 0, int curlm_code = 0);
|
||||
|
||||
void notifyError(const std::string &msg, int curlm_code, const std::string &customId = "");
|
||||
|
||||
void notifyError(const std::string &msg, const std::string &customId, int curle_code);
|
||||
|
||||
private:
|
||||
|
||||
int _connectionTimeout;
|
||||
|
||||
ErrorCallback _onError;
|
||||
|
||||
ProgressCallback _onProgress;
|
||||
|
||||
SuccessCallback _onSuccess;
|
||||
|
||||
std::string getFileNameFromUrl(const std::string &srcUrl);
|
||||
|
||||
void clearBatchDownloadData();
|
||||
|
||||
std::vector<FileDescriptor *> _files;
|
||||
|
||||
std::vector<ProgressData *> _progDatas;
|
||||
|
||||
FileUtils *_fileUtils;
|
||||
|
||||
bool _supportResuming;
|
||||
};
|
||||
|
||||
int downloadProgressFunc(Downloader::ProgressData *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded);
|
||||
|
||||
NS_CC_EXT_END
|
||||
|
||||
#endif /* defined(__Downloader__) */
|
|
@ -0,0 +1,481 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "Manifest.h"
|
||||
#include "json/filestream.h"
|
||||
#include "json/prettywriter.h"
|
||||
#include "json/stringbuffer.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#define KEY_VERSION "version"
|
||||
#define KEY_PACKAGE_URL "packageUrl"
|
||||
#define KEY_MANIFEST_URL "remoteManifestUrl"
|
||||
#define KEY_VERSION_URL "remoteVersionUrl"
|
||||
#define KEY_GROUP_VERSIONS "groupVersions"
|
||||
#define KEY_ENGINE_VERSION "engineVersion"
|
||||
#define KEY_ASSETS "assets"
|
||||
#define KEY_COMPRESSED_FILES "compressedFiles"
|
||||
#define KEY_SEARCH_PATHS "searchPaths"
|
||||
|
||||
#define KEY_PATH "path"
|
||||
#define KEY_MD5 "md5"
|
||||
#define KEY_GROUP "group"
|
||||
#define KEY_COMPRESSED "compressed"
|
||||
#define KEY_COMPRESSED_FILE "compressedFile"
|
||||
#define KEY_DOWNLOAD_STATE "downloadState"
|
||||
|
||||
NS_CC_EXT_BEGIN
|
||||
|
||||
Manifest::Manifest(const std::string& manifestUrl/* = ""*/)
|
||||
: _versionLoaded(false)
|
||||
, _loaded(false)
|
||||
, _manifestRoot("")
|
||||
, _remoteManifestUrl("")
|
||||
, _remoteVersionUrl("")
|
||||
, _version("")
|
||||
, _engineVer("")
|
||||
{
|
||||
// Init variables
|
||||
_fileUtils = FileUtils::getInstance();
|
||||
if (manifestUrl.size() > 0)
|
||||
parse(manifestUrl);
|
||||
}
|
||||
|
||||
void Manifest::parse(const std::string& manifestUrl)
|
||||
{
|
||||
clear();
|
||||
std::string content;
|
||||
if (_fileUtils->isFileExist(manifestUrl))
|
||||
{
|
||||
// Load file content
|
||||
content = _fileUtils->getStringFromFile(manifestUrl);
|
||||
|
||||
if (content.size() == 0)
|
||||
{
|
||||
CCLOG("Fail to retrieve local file content: %s\n", manifestUrl.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse file with rapid json
|
||||
_json.Parse<0>(content.c_str());
|
||||
// Print error
|
||||
if (_json.HasParseError()) {
|
||||
size_t offset = _json.GetErrorOffset();
|
||||
if (offset > 0)
|
||||
offset--;
|
||||
std::string errorSnippet = content.substr(offset, 10);
|
||||
CCLOG("File parse error %s at <%s>\n", _json.GetParseError(), errorSnippet.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_json.IsObject())
|
||||
{
|
||||
// Register the local manifest root
|
||||
size_t found = manifestUrl.find_last_of("/\\");
|
||||
if (found != std::string::npos)
|
||||
{
|
||||
_manifestRoot = manifestUrl.substr(0, found+1);
|
||||
}
|
||||
loadManifest(_json);
|
||||
}
|
||||
}
|
||||
|
||||
bool Manifest::isVersionLoaded() const
|
||||
{
|
||||
return _versionLoaded;
|
||||
}
|
||||
bool Manifest::isLoaded() const
|
||||
{
|
||||
return _loaded;
|
||||
}
|
||||
|
||||
bool Manifest::versionEquals(const Manifest *b) const
|
||||
{
|
||||
// Check manifest version
|
||||
if (_version != b->getVersion())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Check group versions
|
||||
else
|
||||
{
|
||||
std::vector<std::string> bGroups = b->getGroups();
|
||||
std::unordered_map<std::string, std::string> bGroupVer = b->getGroupVerions();
|
||||
// Check group size
|
||||
if (bGroups.size() != _groups.size())
|
||||
return false;
|
||||
|
||||
// Check groups version
|
||||
for (int i = 0; i < _groups.size(); ++i) {
|
||||
std::string gid =_groups[i];
|
||||
// Check group name
|
||||
if (gid != bGroups[i])
|
||||
return false;
|
||||
// Check group version
|
||||
if (_groupVer.at(gid) != bGroupVer.at(gid))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, Manifest::AssetDiff> Manifest::genDiff(const Manifest *b) const
|
||||
{
|
||||
std::unordered_map<std::string, AssetDiff> diff_map;
|
||||
std::unordered_map<std::string, Asset> bAssets = b->getAssets();
|
||||
|
||||
std::string key;
|
||||
Asset valueA;
|
||||
Asset valueB;
|
||||
std::unordered_map<std::string, Asset>::const_iterator valueIt, it;
|
||||
for (it = _assets.begin(); it != _assets.end(); ++it)
|
||||
{
|
||||
key = it->first;
|
||||
valueA = it->second;
|
||||
|
||||
// Deleted
|
||||
valueIt = bAssets.find(key);
|
||||
if (valueIt == bAssets.cend()) {
|
||||
AssetDiff diff;
|
||||
diff.asset = valueA;
|
||||
diff.type = DiffType::DELETED;
|
||||
diff_map.emplace(key, diff);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Modified
|
||||
valueB = valueIt->second;
|
||||
if (valueA.md5 != valueB.md5) {
|
||||
AssetDiff diff;
|
||||
diff.asset = valueB;
|
||||
diff.type = DiffType::MODIFIED;
|
||||
diff_map.emplace(key, diff);
|
||||
}
|
||||
}
|
||||
|
||||
for (it = bAssets.begin(); it != bAssets.end(); ++it)
|
||||
{
|
||||
key = it->first;
|
||||
valueB = it->second;
|
||||
|
||||
// Added
|
||||
valueIt = _assets.find(key);
|
||||
if (valueIt == _assets.cend()) {
|
||||
AssetDiff diff;
|
||||
diff.asset = valueB;
|
||||
diff.type = DiffType::ADDED;
|
||||
diff_map.emplace(key, diff);
|
||||
}
|
||||
}
|
||||
|
||||
return diff_map;
|
||||
}
|
||||
|
||||
void Manifest::genResumeAssetsList(Downloader::DownloadUnits *units) const
|
||||
{
|
||||
for (auto it = _assets.begin(); it != _assets.end(); ++it)
|
||||
{
|
||||
Asset asset = it->second;
|
||||
|
||||
if (asset.downloadState != DownloadState::SUCCESSED)
|
||||
{
|
||||
Downloader::DownloadUnit unit;
|
||||
unit.customId = it->first;
|
||||
unit.srcUrl = _packageUrl + asset.path;
|
||||
unit.storagePath = _manifestRoot + asset.path;
|
||||
if (asset.downloadState == DownloadState::DOWNLOADING)
|
||||
{
|
||||
unit.resumeDownload = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
unit.resumeDownload = false;
|
||||
}
|
||||
units->emplace(unit.customId, unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Manifest::prependSearchPaths()
|
||||
{
|
||||
std::vector<std::string> searchPaths = FileUtils::getInstance()->getSearchPaths();
|
||||
std::vector<std::string>::iterator iter = searchPaths.begin();
|
||||
searchPaths.insert(iter, _manifestRoot);
|
||||
|
||||
for (int i = (int)_searchPaths.size()-1; i >= 0; i--)
|
||||
{
|
||||
std::string path = _searchPaths[i];
|
||||
if (path.size() > 0 && path[path.size() - 1] != '/')
|
||||
path.append("/");
|
||||
path = _manifestRoot + path;
|
||||
iter = searchPaths.begin();
|
||||
searchPaths.insert(iter, path);
|
||||
}
|
||||
FileUtils::getInstance()->setSearchPaths(searchPaths);
|
||||
}
|
||||
|
||||
|
||||
const std::string& Manifest::getPackageUrl() const
|
||||
{
|
||||
return _packageUrl;
|
||||
}
|
||||
|
||||
const std::string& Manifest::getManifestFileUrl() const
|
||||
{
|
||||
return _remoteManifestUrl;
|
||||
}
|
||||
|
||||
const std::string& Manifest::getVersionFileUrl() const
|
||||
{
|
||||
return _remoteVersionUrl;
|
||||
}
|
||||
|
||||
const std::string& Manifest::getVersion() const
|
||||
{
|
||||
return _version;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& Manifest::getGroups() const
|
||||
{
|
||||
return _groups;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string, std::string>& Manifest::getGroupVerions() const
|
||||
{
|
||||
return _groupVer;
|
||||
}
|
||||
|
||||
const std::string& Manifest::getGroupVersion(const std::string &group) const
|
||||
{
|
||||
return _groupVer.at(group);
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string, Manifest::Asset>& Manifest::getAssets() const
|
||||
{
|
||||
return _assets;
|
||||
}
|
||||
|
||||
void Manifest::setAssetDownloadState(const std::string &key, const Manifest::DownloadState &state)
|
||||
{
|
||||
auto valueIt = _assets.find(key);
|
||||
if (valueIt != _assets.end())
|
||||
{
|
||||
valueIt->second.downloadState = state;
|
||||
|
||||
// Update json object
|
||||
if(_json.IsObject())
|
||||
{
|
||||
if ( _json.HasMember(KEY_ASSETS) )
|
||||
{
|
||||
rapidjson::Value &assets = _json[KEY_ASSETS];
|
||||
if (assets.IsObject())
|
||||
{
|
||||
for (rapidjson::Value::MemberIterator itr = assets.MemberonBegin(); itr != assets.MemberonEnd(); ++itr)
|
||||
{
|
||||
std::string jkey = itr->name.GetString();
|
||||
if (jkey == key) {
|
||||
rapidjson::Value &entry = itr->value;
|
||||
rapidjson::Value &value = entry[KEY_DOWNLOAD_STATE];
|
||||
if (value.IsInt())
|
||||
{
|
||||
value.SetInt((int)state);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.AddMember<int>(KEY_DOWNLOAD_STATE, (int)state, _json.GetAllocator());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Manifest::clear()
|
||||
{
|
||||
if (_versionLoaded || _loaded)
|
||||
{
|
||||
_groups.clear();
|
||||
_groupVer.clear();
|
||||
|
||||
_remoteManifestUrl = "";
|
||||
_remoteVersionUrl = "";
|
||||
_version = "";
|
||||
_engineVer = "";
|
||||
|
||||
_versionLoaded = false;
|
||||
}
|
||||
|
||||
if (_loaded)
|
||||
{
|
||||
_assets.clear();
|
||||
_searchPaths.clear();
|
||||
_loaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
Manifest::Asset Manifest::parseAsset(const std::string &path, const rapidjson::Value &json)
|
||||
{
|
||||
Asset asset;
|
||||
asset.path = path;
|
||||
|
||||
if ( json.HasMember(KEY_MD5) && json[KEY_MD5].IsString() )
|
||||
{
|
||||
asset.md5 = json[KEY_MD5].GetString();
|
||||
}
|
||||
else asset.md5 = "";
|
||||
|
||||
if ( json.HasMember(KEY_PATH) && json[KEY_PATH].IsString() )
|
||||
{
|
||||
asset.path = json[KEY_PATH].GetString();
|
||||
}
|
||||
|
||||
if ( json.HasMember(KEY_COMPRESSED) && json[KEY_COMPRESSED].IsBool() )
|
||||
{
|
||||
asset.compressed = json[KEY_COMPRESSED].GetBool();
|
||||
}
|
||||
else asset.compressed = false;
|
||||
|
||||
if ( json.HasMember(KEY_DOWNLOAD_STATE) && json[KEY_DOWNLOAD_STATE].IsInt() )
|
||||
{
|
||||
asset.downloadState = (DownloadState)(json[KEY_DOWNLOAD_STATE].GetInt());
|
||||
}
|
||||
else asset.downloadState = DownloadState::UNSTARTED;
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
void Manifest::loadVersion(const rapidjson::Document &json)
|
||||
{
|
||||
// Retrieve remote manifest url
|
||||
if ( json.HasMember(KEY_MANIFEST_URL) && json[KEY_MANIFEST_URL].IsString() )
|
||||
{
|
||||
_remoteManifestUrl = json[KEY_MANIFEST_URL].GetString();
|
||||
}
|
||||
|
||||
// Retrieve remote version url
|
||||
if ( json.HasMember(KEY_VERSION_URL) && json[KEY_VERSION_URL].IsString() )
|
||||
{
|
||||
_remoteVersionUrl = json[KEY_VERSION_URL].GetString();
|
||||
}
|
||||
|
||||
// Retrieve local version
|
||||
if ( json.HasMember(KEY_VERSION) && json[KEY_VERSION].IsString() )
|
||||
{
|
||||
_version = json[KEY_VERSION].GetString();
|
||||
}
|
||||
|
||||
// Retrieve local group version
|
||||
if ( json.HasMember(KEY_GROUP_VERSIONS) )
|
||||
{
|
||||
const rapidjson::Value& groupVers = json[KEY_GROUP_VERSIONS];
|
||||
if (groupVers.IsObject())
|
||||
{
|
||||
for (rapidjson::Value::ConstMemberIterator itr = groupVers.MemberonBegin(); itr != groupVers.MemberonEnd(); ++itr)
|
||||
{
|
||||
std::string group = itr->name.GetString();
|
||||
std::string version = "0";
|
||||
if (itr->value.IsString())
|
||||
{
|
||||
version = itr->value.GetString();
|
||||
}
|
||||
_groups.push_back(group);
|
||||
_groupVer.emplace(group, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve local engine version
|
||||
if ( json.HasMember(KEY_ENGINE_VERSION) && json[KEY_ENGINE_VERSION].IsString() )
|
||||
{
|
||||
_engineVer = json[KEY_ENGINE_VERSION].GetString();
|
||||
}
|
||||
|
||||
_versionLoaded = true;
|
||||
}
|
||||
|
||||
void Manifest::loadManifest(const rapidjson::Document &json)
|
||||
{
|
||||
loadVersion(json);
|
||||
|
||||
// Retrieve package url
|
||||
if ( json.HasMember(KEY_PACKAGE_URL) && json[KEY_PACKAGE_URL].IsString() )
|
||||
{
|
||||
_packageUrl = json[KEY_PACKAGE_URL].GetString();
|
||||
// Append automatically "/"
|
||||
if (_packageUrl.size() > 0 && _packageUrl[_packageUrl.size() - 1] != '/')
|
||||
{
|
||||
_packageUrl.append("/");
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve all assets
|
||||
if ( json.HasMember(KEY_ASSETS) )
|
||||
{
|
||||
const rapidjson::Value& assets = json[KEY_ASSETS];
|
||||
if (assets.IsObject())
|
||||
{
|
||||
for (rapidjson::Value::ConstMemberIterator itr = assets.MemberonBegin(); itr != assets.MemberonEnd(); ++itr)
|
||||
{
|
||||
std::string key = itr->name.GetString();
|
||||
Asset asset = parseAsset(key, itr->value);
|
||||
_assets.emplace(key, asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve all search paths
|
||||
if ( json.HasMember(KEY_SEARCH_PATHS) )
|
||||
{
|
||||
const rapidjson::Value& paths = json[KEY_SEARCH_PATHS];
|
||||
if (paths.IsArray())
|
||||
{
|
||||
for (rapidjson::SizeType i = 0; i < paths.Size(); ++i)
|
||||
{
|
||||
if (paths[i].IsString()) {
|
||||
_searchPaths.push_back(paths[i].GetString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_loaded = true;
|
||||
}
|
||||
|
||||
void Manifest::saveToFile(const std::string &filepath)
|
||||
{
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
|
||||
_json.Accept(writer);
|
||||
|
||||
std::ofstream output(filepath, std::ofstream::out);
|
||||
if(!output.bad())
|
||||
output << buffer.GetString() << std::endl;
|
||||
}
|
||||
|
||||
NS_CC_EXT_END
|
|
@ -0,0 +1,207 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2013 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __Manifest__
|
||||
#define __Manifest__
|
||||
|
||||
#include "extensions/ExtensionMacros.h"
|
||||
#include "extensions/ExtensionExport.h"
|
||||
#include "Downloader.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "json/document.h"
|
||||
|
||||
NS_CC_EXT_BEGIN
|
||||
|
||||
|
||||
class CC_EX_DLL Manifest : public Ref
|
||||
{
|
||||
public:
|
||||
|
||||
friend class AssetsManagerEx;
|
||||
|
||||
//! The type of difference
|
||||
enum class DiffType {
|
||||
ADDED,
|
||||
DELETED,
|
||||
MODIFIED
|
||||
};
|
||||
|
||||
enum class DownloadState {
|
||||
UNSTARTED,
|
||||
DOWNLOADING,
|
||||
SUCCESSED
|
||||
};
|
||||
|
||||
//! Asset object
|
||||
struct Asset {
|
||||
std::string md5;
|
||||
std::string path;
|
||||
bool compressed;
|
||||
DownloadState downloadState;
|
||||
};
|
||||
|
||||
//! Object indicate the difference between two Assets
|
||||
struct AssetDiff {
|
||||
Asset asset;
|
||||
DiffType type;
|
||||
};
|
||||
|
||||
/** @brief Check whether the version informations have been fully loaded
|
||||
*/
|
||||
bool isVersionLoaded() const;
|
||||
|
||||
/** @brief Check whether the manifest have been fully loaded
|
||||
*/
|
||||
bool isLoaded() const;
|
||||
|
||||
/** @brief Gets remote package url.
|
||||
*/
|
||||
const std::string& getPackageUrl() const;
|
||||
|
||||
/** @brief Gets remote manifest file url.
|
||||
*/
|
||||
const std::string& getManifestFileUrl() const;
|
||||
|
||||
/** @brief Gets remote version file url.
|
||||
*/
|
||||
const std::string& getVersionFileUrl() const;
|
||||
|
||||
/** @brief Gets manifest version.
|
||||
*/
|
||||
const std::string& getVersion() const;
|
||||
|
||||
protected:
|
||||
|
||||
/** @brief Constructor for Manifest class
|
||||
@param manifestUrl Url of the local manifest
|
||||
*/
|
||||
Manifest(const std::string& manifestUrl = "");
|
||||
|
||||
/** @brief Parse the manifest file information into this manifest
|
||||
* @param manifestUrl Url of the local manifest
|
||||
*/
|
||||
void parse(const std::string& manifestUrl);
|
||||
|
||||
/** @brief Check whether the version of this manifest equals to another.
|
||||
* @param b The other manifest
|
||||
*/
|
||||
bool versionEquals(const Manifest *b) const;
|
||||
|
||||
/** @brief Generate difference between this Manifest and another.
|
||||
* @param b The other manifest
|
||||
*/
|
||||
std::unordered_map<std::string, AssetDiff> genDiff(const Manifest *b) const;
|
||||
|
||||
/** @brief Generate resuming download assets list
|
||||
* @param units The download units reference to be modified by the generation result
|
||||
*/
|
||||
void genResumeAssetsList(Downloader::DownloadUnits *units) const;
|
||||
|
||||
/** @brief Prepend all search paths to the FileUtils.
|
||||
*/
|
||||
void prependSearchPaths();
|
||||
|
||||
void loadVersion(const rapidjson::Document &json);
|
||||
|
||||
void loadManifest(const rapidjson::Document &json);
|
||||
|
||||
void saveToFile(const std::string &filepath);
|
||||
|
||||
Asset parseAsset(const std::string &path, const rapidjson::Value &json);
|
||||
|
||||
void clear();
|
||||
|
||||
/** @brief Gets all groups.
|
||||
*/
|
||||
const std::vector<std::string>& getGroups() const;
|
||||
|
||||
/** @brief Gets all groups version.
|
||||
*/
|
||||
const std::unordered_map<std::string, std::string>& getGroupVerions() const;
|
||||
|
||||
/** @brief Gets version for the given group.
|
||||
* @param group Key of the requested group
|
||||
*/
|
||||
const std::string& getGroupVersion(const std::string &group) const;
|
||||
|
||||
/** @brief Gets assets.
|
||||
*/
|
||||
const std::unordered_map<std::string, Asset>& getAssets() const;
|
||||
|
||||
/** @brief Set the download state for an asset
|
||||
* @param key Key of the asset to set
|
||||
* @param state The current download state of the asset
|
||||
*/
|
||||
void setAssetDownloadState(const std::string &key, const DownloadState &state);
|
||||
|
||||
private:
|
||||
|
||||
//! Indicate whether the version informations have been fully loaded
|
||||
bool _versionLoaded;
|
||||
|
||||
//! Indicate whether the manifest have been fully loaded
|
||||
bool _loaded;
|
||||
|
||||
//! Reference to the global file utils
|
||||
FileUtils *_fileUtils;
|
||||
|
||||
//! The local manifest root
|
||||
std::string _manifestRoot;
|
||||
|
||||
//! The remote package url
|
||||
std::string _packageUrl;
|
||||
|
||||
//! The remote path of manifest file
|
||||
std::string _remoteManifestUrl;
|
||||
|
||||
//! The remote path of version file [Optional]
|
||||
std::string _remoteVersionUrl;
|
||||
|
||||
//! The version of local manifest
|
||||
std::string _version;
|
||||
|
||||
//! All groups exist in manifest [Optional]
|
||||
std::vector<std::string> _groups;
|
||||
|
||||
//! The versions of all local group [Optional]
|
||||
std::unordered_map<std::string, std::string> _groupVer;
|
||||
|
||||
//! The version of local engine
|
||||
std::string _engineVer;
|
||||
|
||||
//! Full assets list
|
||||
std::unordered_map<std::string, Asset> _assets;
|
||||
|
||||
//! All search paths
|
||||
std::vector<std::string> _searchPaths;
|
||||
|
||||
rapidjson::Document _json;
|
||||
};
|
||||
|
||||
NS_CC_EXT_END
|
||||
#endif /* defined(__Manifest__) */
|
|
@ -13,6 +13,10 @@
|
|||
#include "physics-nodes/CCPhysicsSprite.h"
|
||||
|
||||
#include "assets-manager/AssetsManager.h"
|
||||
#include "assets-manager/AssetsManagerEx.h"
|
||||
#include "assets-manager/CCEventAssetsManagerEx.h"
|
||||
#include "assets-manager/CCEventListenerAssetsManagerEx.h"
|
||||
#include "assets-manager/Manifest.h"
|
||||
#include "ExtensionDeprecated.h"
|
||||
|
||||
#endif /* __COCOS2D_EXT_H__ */
|
||||
|
|
|
@ -1171,6 +1171,14 @@
|
|||
"extensions/GUI/CCScrollView/CCTableViewCell.h",
|
||||
"extensions/assets-manager/AssetsManager.cpp",
|
||||
"extensions/assets-manager/AssetsManager.h",
|
||||
"extensions/assets-manager/CCEventAssetsManager.cpp",
|
||||
"extensions/assets-manager/CCEventAssetsManager.h",
|
||||
"extensions/assets-manager/CCEventListenerAssetsManager.cpp",
|
||||
"extensions/assets-manager/CCEventListenerAssetsManager.h",
|
||||
"extensions/assets-manager/Downloader.cpp",
|
||||
"extensions/assets-manager/Downloader.h",
|
||||
"extensions/assets-manager/Manifest.cpp",
|
||||
"extensions/assets-manager/Manifest.h",
|
||||
"extensions/cocos-ext.h",
|
||||
"extensions/physics-nodes/CCPhysicsDebugNode.cpp",
|
||||
"extensions/physics-nodes/CCPhysicsDebugNode.h",
|
||||
|
|
|
@ -49,6 +49,7 @@ set(TESTS_SRC
|
|||
Classes/DrawPrimitivesTest/DrawPrimitivesTest.cpp
|
||||
Classes/EffectsAdvancedTest/EffectsAdvancedTest.cpp
|
||||
Classes/EffectsTest/EffectsTest.cpp
|
||||
Classes/ExtensionsTest/AssetsManagerExTest/AssetsManagerExTest.cpp
|
||||
Classes/ExtensionsTest/CocosBuilderTest/ButtonTest/ButtonTestLayer.cpp
|
||||
Classes/ExtensionsTest/CocosBuilderTest/CocosBuilderTest.cpp
|
||||
Classes/ExtensionsTest/CocosBuilderTest/HelloCocosBuilder/HelloCocosBuilderLayer.cpp
|
||||
|
|
|
@ -96,6 +96,7 @@ bool AppDelegate::applicationDidFinishLaunching()
|
|||
searchPaths.push_back("ccs-res/hd/scenetest/UIComponentTest");
|
||||
searchPaths.push_back("ccs-res/hd/scenetest/TriggerTest");
|
||||
searchPaths.push_back("ccs-res");
|
||||
searchPaths.push_back("Manifests");
|
||||
director->setContentScaleFactor(resourceSize.height/designSize.height);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
#include "AssetsManagerExTest.h"
|
||||
#include "../../testResource.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
const char* sceneManifests[] = {"AMTestScene1/project.manifest", "AMTestScene2/project.manifest", "AMTestScene3/project.manifest"};
|
||||
const char* storagePaths[] = {"CppTests/AssetsManagerExTest/scene1/", "CppTests/AssetsManagerExTest/scene2/", "CppTests/AssetsManagerExTest/scene3"};
|
||||
const char* backgroundPaths[] = {"Images/background1.jpg", "Images/background2.jpg", "Images/background3.png"};
|
||||
|
||||
AssetsManagerExTestLayer::AssetsManagerExTestLayer(const std::string& spritePath)
|
||||
: _spritePath(spritePath)
|
||||
{
|
||||
}
|
||||
|
||||
AssetsManagerExTestLayer::~AssetsManagerExTestLayer(void)
|
||||
{
|
||||
}
|
||||
|
||||
std::string AssetsManagerExTestLayer::title() const
|
||||
{
|
||||
return "AssetsManagerExTest";
|
||||
}
|
||||
|
||||
void AssetsManagerExTestLayer::onEnter()
|
||||
{
|
||||
BaseTest::onEnter();
|
||||
_background = Sprite::create(_spritePath);
|
||||
if (_background)
|
||||
{
|
||||
addChild(_background, 1);
|
||||
_background->setPosition( VisibleRect::center() );
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerExTestLayer::restartCallback(Ref* sender)
|
||||
{
|
||||
}
|
||||
|
||||
void AssetsManagerExTestLayer::nextCallback(Ref* sender)
|
||||
{
|
||||
if (AssetsManagerExLoaderScene::currentScene < 2)
|
||||
{
|
||||
AssetsManagerExLoaderScene::currentScene++;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssetsManagerExLoaderScene::currentScene = 0;
|
||||
}
|
||||
auto scene = new AssetsManagerExLoaderScene();
|
||||
scene->runThisTest();
|
||||
scene->release();
|
||||
}
|
||||
|
||||
void AssetsManagerExTestLayer::backCallback(Ref* sender)
|
||||
{
|
||||
if (AssetsManagerExLoaderScene::currentScene > 0)
|
||||
{
|
||||
AssetsManagerExLoaderScene::currentScene--;
|
||||
}
|
||||
else AssetsManagerExLoaderScene::currentScene = 2;
|
||||
auto scene = new AssetsManagerExLoaderScene();
|
||||
scene->runThisTest();
|
||||
scene->release();
|
||||
}
|
||||
|
||||
|
||||
AssetsManagerExTestScene::AssetsManagerExTestScene(std::string background)
|
||||
{
|
||||
auto layer = new AssetsManagerExTestLayer(background);
|
||||
addChild(layer);
|
||||
layer->release();
|
||||
}
|
||||
|
||||
void AssetsManagerExTestScene::runThisTest()
|
||||
{
|
||||
}
|
||||
|
||||
int AssetsManagerExLoaderScene::currentScene = 0;
|
||||
AssetsManagerExLoaderScene::AssetsManagerExLoaderScene()
|
||||
: _progress(nullptr)
|
||||
, _amListener(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void AssetsManagerExLoaderScene::runThisTest()
|
||||
{
|
||||
int currentId = currentScene;
|
||||
std::string manifestPath = sceneManifests[currentId], storagePath = FileUtils::getInstance()->getWritablePath() + storagePaths[currentId];
|
||||
CCLOG("Storage path for this test : %s", storagePath.c_str());
|
||||
|
||||
Sprite *sprite = Sprite::create("Images/Icon.png");
|
||||
auto layer = Layer::create();
|
||||
addChild(layer);
|
||||
layer->addChild(sprite);
|
||||
sprite->setPosition( VisibleRect::center() );
|
||||
|
||||
TTFConfig config("fonts/tahoma.ttf", 30);
|
||||
_progress = Label::createWithTTF(config, "0%", TextHAlignment::CENTER);
|
||||
_progress->setPosition( Vec2(VisibleRect::center().x, VisibleRect::center().y + 50) );
|
||||
layer->addChild(_progress);
|
||||
|
||||
_am = AssetsManagerEx::create(manifestPath, storagePath);
|
||||
_am->retain();
|
||||
|
||||
if (!_am->getLocalManifest()->isLoaded())
|
||||
{
|
||||
CCLOG("Fail to update assets, step skipped.");
|
||||
AssetsManagerExTestScene *scene = new AssetsManagerExTestScene(backgroundPaths[currentId]);
|
||||
Director::getInstance()->replaceScene(scene);
|
||||
scene->release();
|
||||
}
|
||||
else
|
||||
{
|
||||
_amListener = cocos2d::extension::EventListenerAssetsManagerEx::create(_am, [currentId, this](EventAssetsManagerEx* event){
|
||||
static int failCount = 0;
|
||||
AssetsManagerExTestScene *scene;
|
||||
switch (event->getEventCode())
|
||||
{
|
||||
case EventAssetsManagerEx::EventCode::ERROR_NO_LOCAL_MANIFEST:
|
||||
{
|
||||
CCLOG("No local manifest file found, skip assets update.");
|
||||
scene = new AssetsManagerExTestScene(backgroundPaths[currentId]);
|
||||
Director::getInstance()->replaceScene(scene);
|
||||
scene->release();
|
||||
}
|
||||
break;
|
||||
case EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION:
|
||||
{
|
||||
std::string assetId = event->getAssetId();
|
||||
float percent = event->getPercent();
|
||||
std::string str;
|
||||
if (assetId == AssetsManagerEx::VERSION_ID)
|
||||
{
|
||||
str = StringUtils::format("Version file: %.2f", percent) + "%";
|
||||
}
|
||||
else if (assetId == AssetsManagerEx::MANIFEST_ID)
|
||||
{
|
||||
str = StringUtils::format("Manifest file: %.2f", percent) + "%";
|
||||
}
|
||||
else
|
||||
{
|
||||
str = StringUtils::format("%.2f", percent) + "%";
|
||||
CCLOG("%.2f Percent", percent);
|
||||
}
|
||||
if (this->_progress != nullptr)
|
||||
this->_progress->setString(str);
|
||||
}
|
||||
break;
|
||||
case EventAssetsManagerEx::EventCode::ERROR_DOWNLOAD_MANIFEST:
|
||||
case EventAssetsManagerEx::EventCode::ERROR_PARSE_MANIFEST:
|
||||
{
|
||||
CCLOG("Fail to download manifest file, update skipped.");
|
||||
scene = new AssetsManagerExTestScene(backgroundPaths[currentId]);
|
||||
Director::getInstance()->replaceScene(scene);
|
||||
scene->release();
|
||||
}
|
||||
break;
|
||||
case EventAssetsManagerEx::EventCode::ALREADY_UP_TO_DATE:
|
||||
case EventAssetsManagerEx::EventCode::UPDATE_FINISHED:
|
||||
{
|
||||
CCLOG("Update finished. %s", event->getMessage().c_str());
|
||||
scene = new AssetsManagerExTestScene(backgroundPaths[currentId]);
|
||||
Director::getInstance()->replaceScene(scene);
|
||||
scene->release();
|
||||
}
|
||||
break;
|
||||
case EventAssetsManagerEx::EventCode::UPDATE_FAILED:
|
||||
{
|
||||
CCLOG("Update failed. %s", event->getMessage().c_str());
|
||||
|
||||
failCount ++;
|
||||
if (failCount < 5)
|
||||
{
|
||||
_am->downloadFailedAssets();
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG("Reach maximum fail count, exit update process");
|
||||
failCount = 0;
|
||||
scene = new AssetsManagerExTestScene(backgroundPaths[currentId]);
|
||||
Director::getInstance()->replaceScene(scene);
|
||||
scene->release();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EventAssetsManagerEx::EventCode::ERROR_UPDATING:
|
||||
{
|
||||
CCLOG("Asset %s : %s", event->getAssetId().c_str(), event->getMessage().c_str());
|
||||
}
|
||||
break;
|
||||
case EventAssetsManagerEx::EventCode::ERROR_DECOMPRESS:
|
||||
{
|
||||
CCLOG("%s", event->getMessage().c_str());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_amListener, 1);
|
||||
|
||||
_am->update();
|
||||
|
||||
Director::getInstance()->replaceScene(this);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerExLoaderScene::onExit()
|
||||
{
|
||||
_eventDispatcher->removeEventListener(_amListener);
|
||||
_am->release();
|
||||
Scene::onExit();
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#ifndef __AssetsManagerEx_Test_H__
|
||||
#define __AssetsManagerEx_Test_H__
|
||||
|
||||
#include "extensions/cocos-ext.h"
|
||||
#include "../../testBasic.h"
|
||||
#include "../../BaseTest.h"
|
||||
|
||||
USING_NS_CC;
|
||||
USING_NS_CC_EXT;
|
||||
|
||||
class AssetsManagerExTestLayer : public BaseTest
|
||||
{
|
||||
public:
|
||||
AssetsManagerExTestLayer(const std::string& spritePath);
|
||||
~AssetsManagerExTestLayer(void);
|
||||
|
||||
virtual std::string title() const;
|
||||
void onEnter();
|
||||
|
||||
virtual void restartCallback(Ref* sender);
|
||||
virtual void nextCallback(Ref* sender);
|
||||
virtual void backCallback(Ref* sender);
|
||||
|
||||
private:
|
||||
Sprite *_background;
|
||||
std::string _spritePath;
|
||||
};
|
||||
|
||||
class AssetsManagerExTestScene : public TestScene
|
||||
{
|
||||
public:
|
||||
AssetsManagerExTestScene(std::string background);
|
||||
virtual void runThisTest() override;
|
||||
};
|
||||
|
||||
class AssetsManagerExLoaderScene : public TestScene
|
||||
{
|
||||
public:
|
||||
AssetsManagerExLoaderScene();
|
||||
|
||||
virtual void runThisTest() override;
|
||||
|
||||
virtual void onExit() override;
|
||||
|
||||
static int currentScene;
|
||||
|
||||
private:
|
||||
AssetsManagerEx *_am;
|
||||
Label *_progress;
|
||||
EventListenerAssetsManagerEx* _amListener;
|
||||
};
|
||||
|
||||
#endif /* defined(__AssetsManagerEx_Test_H__) */
|
|
@ -1,5 +1,6 @@
|
|||
#include "ExtensionsTest.h"
|
||||
#include "../testResource.h"
|
||||
#include "AssetsManagerExTest/AssetsManagerExTest.h"
|
||||
#include "NotificationCenterTest/NotificationCenterTest.h"
|
||||
#include "ControlExtensionTest/CCControlSceneManager.h"
|
||||
#include "CocosBuilderTest/CocosBuilderTest.h"
|
||||
|
@ -29,6 +30,10 @@ static struct {
|
|||
const char *name;
|
||||
std::function<void(Ref* sender)> callback;
|
||||
} g_extensionsTests[] = {
|
||||
{ "AssetsManagerExTest", [](Ref* sender) {
|
||||
AssetsManagerExLoaderScene *scene = new AssetsManagerExLoaderScene();
|
||||
scene->runThisTest();
|
||||
} },
|
||||
{ "NotificationCenterTest", [](Ref* sender) { runNotificationCenterTest(); }
|
||||
},
|
||||
{ "CCControlButtonTest", [](Ref *sender){
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"packageUrl" : "http://tools.itharbors.com/assets_manager/AMTestScene1/",
|
||||
"remoteManifestUrl" : "http://tools.itharbors.com/assets_manager/AMTestScene1/project.manifest",
|
||||
"remoteVersionUrl" : "http://tools.itharbors.com/assets_manager/AMTestScene1/version.manifest",
|
||||
"version" : "1.0.0",
|
||||
"engineVersion" : "3.0 beta",
|
||||
|
||||
"assets" : {
|
||||
"Images/background1.jpg" : {
|
||||
"md5" : "..."
|
||||
}
|
||||
},
|
||||
|
||||
"searchPaths" : [
|
||||
]
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"packageUrl" : "http://tools.itharbors.com/assets_manager/AMTestScene2/",
|
||||
"remoteManifestUrl" : "http://tools.itharbors.com/assets_manager/AMTestScene2/project.manifest",
|
||||
"version" : "1.0.0",
|
||||
"engineVersion" : "3.0 beta",
|
||||
|
||||
"assets" : {
|
||||
"Images/background2.jpg" : {
|
||||
"md5" : "..."
|
||||
}
|
||||
},
|
||||
|
||||
"searchPaths" : [
|
||||
]
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"packageUrl" : "http://tools.itharbors.com/assets_manager/AMTestScene3/",
|
||||
"remoteManifestUrl" : "http://tools.itharbors.com/assets_manager/AMTestScene3/project.manifest",
|
||||
"remoteVersionUrl" : "http://tools.itharbors.com/assets_manager/AMTestScene3/version.manifest",
|
||||
"version" : "1.0.0",
|
||||
"engineVersion" : "3.0 beta",
|
||||
|
||||
"assets" : {
|
||||
"Images/background3.png" : {
|
||||
"md5" : "..."
|
||||
}
|
||||
},
|
||||
|
||||
"searchPaths" : [
|
||||
]
|
||||
}
|
|
@ -49,6 +49,7 @@ LOCAL_SRC_FILES := main.cpp \
|
|||
../../Classes/EffectsAdvancedTest/EffectsAdvancedTest.cpp \
|
||||
../../Classes/EffectsTest/EffectsTest.cpp \
|
||||
../../Classes/ExtensionsTest/ExtensionsTest.cpp \
|
||||
../../Classes/ExtensionsTest/AssetsManagerExTest/AssetsManagerExTest.cpp \
|
||||
../../Classes/ExtensionsTest/CocosBuilderTest/CocosBuilderTest.cpp \
|
||||
../../Classes/ExtensionsTest/CocosBuilderTest/AnimationsTest/AnimationsTestLayer.cpp \
|
||||
../../Classes/ExtensionsTest/CocosBuilderTest/ButtonTest/ButtonTestLayer.cpp \
|
||||
|
|
|
@ -145,6 +145,7 @@
|
|||
<ClCompile Include="..\Classes\ConfigurationTest\ConfigurationTest.cpp" />
|
||||
<ClCompile Include="..\Classes\ConsoleTest\ConsoleTest.cpp" />
|
||||
<ClCompile Include="..\Classes\DataVisitorTest\DataVisitorTest.cpp" />
|
||||
<ClCompile Include="..\Classes\ExtensionsTest\AssetsManagerExTest\AssetsManagerExTest.cpp" />
|
||||
<ClCompile Include="..\Classes\ExtensionsTest\CocosBuilderTest\AnimationsTest\AnimationsTestLayer.cpp" />
|
||||
<ClCompile Include="..\Classes\ExtensionsTest\CocosBuilderTest\TimelineCallbackTest\TimelineCallbackTestLayer.cpp" />
|
||||
<ClCompile Include="..\Classes\ExtensionsTest\CocoStudioActionTimelineTest\ActionTimelineTestScene.cpp" />
|
||||
|
@ -334,6 +335,7 @@
|
|||
<ClInclude Include="..\Classes\ConfigurationTest\ConfigurationTest.h" />
|
||||
<ClInclude Include="..\Classes\ConsoleTest\ConsoleTest.h" />
|
||||
<ClInclude Include="..\Classes\DataVisitorTest\DataVisitorTest.h" />
|
||||
<ClInclude Include="..\Classes\ExtensionsTest\AssetsManagerExTest\AssetsManagerExTest.h" />
|
||||
<ClInclude Include="..\Classes\ExtensionsTest\CocosBuilderTest\AnimationsTest\AnimationsLayerLoader.h" />
|
||||
<ClInclude Include="..\Classes\ExtensionsTest\CocosBuilderTest\AnimationsTest\AnimationsTestLayer.h" />
|
||||
<ClInclude Include="..\Classes\ExtensionsTest\CocosBuilderTest\TimelineCallbackTest\TimelineCallbackLayerLoader.h" />
|
||||
|
|
|
@ -331,6 +331,9 @@
|
|||
<Filter Include="Classes\BillBoardTest">
|
||||
<UniqueIdentifier>{54a30b92-ddfb-420e-908b-886c23c21cf1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Classes\ExtensionsTest\AssetsManagerExTest">
|
||||
<UniqueIdentifier>{f6c2eb6d-ad25-4287-a2a4-1c0d7382a49f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Classes\UITest\CocostudioGUISceneTest\UIWebViewTest">
|
||||
<UniqueIdentifier>{a0b90b93-5575-4729-9afc-8a3839b378ac}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
@ -876,6 +879,9 @@
|
|||
<ClCompile Include="..\Classes\BillBoardTest\BillBoardTest.cpp">
|
||||
<Filter>Classes\BillBoardTest</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Classes\ExtensionsTest\AssetsManagerExTest\AssetsManagerExTest.cpp">
|
||||
<Filter>Classes\ExtensionsTest\AssetsManagerExTest</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Classes\LightTest\LightTest.cpp">
|
||||
<Filter>Classes\LightTest</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1622,6 +1628,9 @@
|
|||
<ClInclude Include="..\Classes\BillBoardTest\BillBoardTest.h">
|
||||
<Filter>Classes\BillBoardTest</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Classes\ExtensionsTest\AssetsManagerExTest\AssetsManagerExTest.h">
|
||||
<Filter>Classes\ExtensionsTest\AssetsManagerExTest</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Classes\LightTest\LightTest.h">
|
||||
<Filter>Classes\LightTest</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef COCOS2DX_COCOS_SCRIPTING_LUA_BINDINGS_LUA_ASSETSMANAGER_TEST_SAMPLE_H
|
||||
#define COCOS2DX_COCOS_SCRIPTING_LUA_BINDINGS_LUA_ASSETSMANAGER_TEST_SAMPLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "tolua++.h"
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The apis which are bound in this file are temporary for the assetsmanager test sample.After the completion of some systems like fileutils,these apis will be deprecated
|
||||
*/
|
||||
TOLUA_API int register_assetsmanager_test_sample(lua_State* tolua_S);
|
||||
|
||||
#endif // #ifndef COCOS2DX_COCOS_SCRIPTING_LUA_BINDINGS_LUA_ASSETSMANAGER_TEST_SAMPLE_H
|
|
@ -1,4 +1,4 @@
|
|||
#include "lua_assetsmanager_test_sample.h"
|
||||
#include "lua_assetsmanagerex_test_sample.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -141,7 +141,7 @@ tolua_lerror:
|
|||
#endif
|
||||
}
|
||||
|
||||
int register_assetsmanager_test_sample(lua_State* L)
|
||||
int register_assetsmanagerex_test_sample(lua_State* L)
|
||||
{
|
||||
tolua_open(L);
|
||||
tolua_module(L, NULL, 0);
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef COCOS2DX_COCOS_SCRIPTING_LUA_BINDINGS_LUA_ASSETSMANAGEREX_TEST_SAMPLE_H
|
||||
#define COCOS2DX_COCOS_SCRIPTING_LUA_BINDINGS_LUA_ASSETSMANAGEREX_TEST_SAMPLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "tolua++.h"
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The apis which are bound in this file are temporary for the assetsmanagerex test sample.After the completion of some systems like fileutils,these apis will be deprecated
|
||||
*/
|
||||
TOLUA_API int register_assetsmanagerex_test_sample(lua_State* tolua_S);
|
||||
|
||||
#endif // #ifndef COCOS2DX_COCOS_SCRIPTING_LUA_BINDINGS_LUA_ASSETSMANAGEREX_TEST_SAMPLE_H
|
|
@ -15,7 +15,7 @@
|
|||
<ClInclude Include="main.h">
|
||||
<Filter>win32</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Classes\lua_assetsmanager_test_sample.h">
|
||||
<ClInclude Include="..\Classes\lua_assetsmanagerex_test_sample.h">
|
||||
<Filter>Classes</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Classes\lua_module_register.h">
|
||||
|
@ -32,7 +32,7 @@
|
|||
<ClCompile Include="main.cpp">
|
||||
<Filter>win32</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Classes\lua_assetsmanager_test_sample.cpp">
|
||||
<ClCompile Include="..\Classes\lua_assetsmanagerex_test_sample.cpp">
|
||||
<Filter>Classes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Classes\lua_test_bindings.cpp">
|
||||
|
|
|
@ -0,0 +1,336 @@
|
|||
local targetPlatform = cc.Application:getInstance():getTargetPlatform()
|
||||
|
||||
local sceneID =
|
||||
{
|
||||
"AMTestScene1",
|
||||
"AMTestScene2",
|
||||
"AMTestScene3",
|
||||
}
|
||||
|
||||
local sceneManifests =
|
||||
{
|
||||
"Manifests/AMTestScene1/project.manifest",
|
||||
"Manifests/AMTestScene2/project.manifest",
|
||||
"Manifests/AMTestScene3/project.manifest"
|
||||
}
|
||||
|
||||
--UNCHECK
|
||||
local storagePaths =
|
||||
{
|
||||
"LuaTests/AssetsManagerExTest/scene1",
|
||||
"LuaTests/AssetsManagerExTest/scene2",
|
||||
"LuaTests/AssetsManagerExTest/scene3",
|
||||
}
|
||||
|
||||
local backgroundPaths =
|
||||
{
|
||||
"Images/background1.jpg",
|
||||
"Images/background2.jpg",
|
||||
"Images/background3.png"
|
||||
}
|
||||
|
||||
-------------------------------------
|
||||
-- AssetsManagerEx1 Test
|
||||
-------------------------------------
|
||||
local AMTestScene1 = {}
|
||||
AMTestScene1.__index = AMTestScene1
|
||||
|
||||
function AMTestScene1.create()
|
||||
|
||||
local layer = cc.Layer:create()
|
||||
|
||||
local am = nil
|
||||
|
||||
local function onEnter()
|
||||
|
||||
Helper.initWithLayer(layer)
|
||||
Helper.titleLabel:setString("AssetsManagerExTest1")
|
||||
|
||||
local sprite = cc.Sprite:create("Images/Icon.png")
|
||||
layer:addChild(sprite)
|
||||
sprite:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y))
|
||||
|
||||
local ttfConfig = {}
|
||||
ttfConfig.fontFilePath = "fonts/arial.ttf"
|
||||
ttfConfig.fontSize = 40
|
||||
|
||||
local progress = cc.Label:createWithTTF(ttfConfig, "0%", cc.VERTICAL_TEXT_ALIGNMENT_CENTER)
|
||||
progress:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y + 50))
|
||||
layer:addChild(progress)
|
||||
am = cc.AssetsManagerEx:create("Manifests/AMTestScene1/project.manifest", "LuaTests/AssetsManagerExTest/scene1")
|
||||
am:retain()
|
||||
|
||||
if not am:getLocalManifest():isLoaded() then
|
||||
print("Fail to update assets, step skipped.")
|
||||
local background = cc.Sprite:create("Images/background1.jpg")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
else
|
||||
local function onUpdateEvent(event)
|
||||
local eventCode = event:getEventCode()
|
||||
if eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then
|
||||
print("No local manifest file found, skip assets update.")
|
||||
local background = cc.Sprite:create("Images/background1.jpg")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION then
|
||||
local assetId = event:getAssetId()
|
||||
local percent = event:getPercent()
|
||||
local strInfo = ""
|
||||
|
||||
if assetId == cc.AssetsManagerExStatic.VERSION_ID then
|
||||
strInfo = string.format("Version file: %d%%", percent)
|
||||
elseif assetId == cc.AssetsManagerExStatic.MANIFEST_ID then
|
||||
strInfo = string.format("Manifest file: %d%%", percent)
|
||||
else
|
||||
strInfo = string.format("%d%%", percent)
|
||||
end
|
||||
progress:setString(strInfo)
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST or
|
||||
eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST then
|
||||
print("Fail to download manifest file, update skipped.")
|
||||
local background = cc.Sprite:create("Images/background1.jpg")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE or
|
||||
eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then
|
||||
print("Update finished.")
|
||||
local background = cc.Sprite:create("Images/background1.jpg")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_UPDATING then
|
||||
print("Asset ", event:getAssetId(), ", ", event:getMessage())
|
||||
local background = cc.Sprite:create("Images/background1.jpg")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
end
|
||||
end
|
||||
local listener = cc.EventListenerAssetsManagerEx:create(am,onUpdateEvent)
|
||||
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(listener, 1)
|
||||
|
||||
am:update()
|
||||
end
|
||||
end
|
||||
|
||||
local function onNodeEvent(event)
|
||||
if "enter" == event then
|
||||
onEnter()
|
||||
elseif "exit" == event then
|
||||
am:release()
|
||||
end
|
||||
end
|
||||
layer:registerScriptHandler(onNodeEvent)
|
||||
|
||||
return layer
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------
|
||||
-- AssetsManagerEx2 Test
|
||||
-------------------------------------
|
||||
local AMTestScene2 = {}
|
||||
AMTestScene2.__index = AMTestScene2
|
||||
|
||||
function AMTestScene2.create()
|
||||
|
||||
local layer = cc.Layer:create()
|
||||
|
||||
local am = nil
|
||||
|
||||
local function onEnter()
|
||||
|
||||
Helper.initWithLayer(layer)
|
||||
Helper.titleLabel:setString("AssetsManagerExTest2")
|
||||
|
||||
local sprite = cc.Sprite:create("Images/Icon.png")
|
||||
layer:addChild(sprite)
|
||||
sprite:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y))
|
||||
|
||||
local ttfConfig = {}
|
||||
ttfConfig.fontFilePath = "fonts/arial.ttf"
|
||||
ttfConfig.fontSize = 40
|
||||
|
||||
local progress = cc.Label:createWithTTF(ttfConfig, "0%", cc.VERTICAL_TEXT_ALIGNMENT_CENTER)
|
||||
progress:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y + 50))
|
||||
layer:addChild(progress)
|
||||
|
||||
am = cc.AssetsManagerEx:create("Manifests/AMTestScene2/project.manifest", "LuaTests/AssetsManagerExTest/scene2")
|
||||
am:retain()
|
||||
|
||||
if not am:getLocalManifest():isLoaded() then
|
||||
print("Fail to update assets, step skipped.")
|
||||
local background = cc.Sprite:create("Images/background2.jpg")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
else
|
||||
local function onUpdateEvent(event)
|
||||
local eventCode = event:getEventCode()
|
||||
if eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then
|
||||
print("No local manifest file found, skip assets update.")
|
||||
local background = cc.Sprite:create("Images/background2.jpg")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION then
|
||||
local assetId = event:getAssetId()
|
||||
local percent = event:getPercent()
|
||||
local strInfo = ""
|
||||
|
||||
if assetId == cc.AssetsManagerExStatic.VERSION_ID then
|
||||
strInfo = string.format("Version file: %d%%", percent)
|
||||
elseif assetId == cc.AssetsManagerExStatic.MANIFEST_ID then
|
||||
strInfo = string.format("Manifest file: %d%%", percent)
|
||||
else
|
||||
strInfo = string.format("%d%%", percent)
|
||||
end
|
||||
progress:setString(strInfo)
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST or
|
||||
eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST then
|
||||
print("Fail to download manifest file, update skipped.")
|
||||
local background = cc.Sprite:create("Images/background2.jpg")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE or
|
||||
eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then
|
||||
print("Update finished.")
|
||||
local background = cc.Sprite:create("Images/background2.jpg")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_UPDATING then
|
||||
print("Asset ", event:getAssetId(), ", ", event:getMessage())
|
||||
local background = cc.Sprite:create("Images/background2.jpg")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
end
|
||||
end
|
||||
local listener = cc.EventListenerAssetsManagerEx:create(am,onUpdateEvent)
|
||||
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(listener, 1)
|
||||
|
||||
am:update()
|
||||
end
|
||||
end
|
||||
|
||||
local function onNodeEvent(event)
|
||||
if "enter" == event then
|
||||
onEnter()
|
||||
elseif "exit" == event then
|
||||
am:release()
|
||||
end
|
||||
end
|
||||
layer:registerScriptHandler(onNodeEvent)
|
||||
|
||||
return layer
|
||||
end
|
||||
|
||||
-------------------------------------
|
||||
-- AssetsManagerEx3 Test
|
||||
-------------------------------------
|
||||
local AMTestScene3 = {}
|
||||
AMTestScene3.__index = AMTestScene3
|
||||
|
||||
function AMTestScene3.create()
|
||||
|
||||
local layer = cc.Layer:create()
|
||||
|
||||
local am = nil
|
||||
|
||||
local function onEnter()
|
||||
|
||||
Helper.initWithLayer(layer)
|
||||
Helper.titleLabel:setString("AssetsManagerExTest3")
|
||||
|
||||
local sprite = cc.Sprite:create("Images/Icon.png")
|
||||
layer:addChild(sprite)
|
||||
sprite:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y))
|
||||
|
||||
local ttfConfig = {}
|
||||
ttfConfig.fontFilePath = "fonts/arial.ttf"
|
||||
ttfConfig.fontSize = 40
|
||||
|
||||
local progress = cc.Label:createWithTTF(ttfConfig, "0%", cc.VERTICAL_TEXT_ALIGNMENT_CENTER)
|
||||
progress:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y + 50))
|
||||
layer:addChild(progress)
|
||||
|
||||
am = cc.AssetsManagerEx:create("Manifests/AMTestScene3/project.manifest", "LuaTests/AssetsManagerExTest/scene3")
|
||||
am:retain()
|
||||
|
||||
if not am:getLocalManifest():isLoaded() then
|
||||
print("Fail to update assets, step skipped.")
|
||||
local background = cc.Sprite:create("Images/background3.png")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
else
|
||||
local function onUpdateEvent(event)
|
||||
local eventCode = event:getEventCode()
|
||||
if eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then
|
||||
print("No local manifest file found, skip assets update.")
|
||||
local background = cc.Sprite:create("Images/background3.png")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION then
|
||||
local assetId = event:getAssetId()
|
||||
local percent = event:getPercent()
|
||||
local strInfo = ""
|
||||
|
||||
if assetId == cc.AssetsManagerExStatic.VERSION_ID then
|
||||
strInfo = string.format("Version file: %d%%", percent)
|
||||
elseif assetId == cc.AssetsManagerExStatic.MANIFEST_ID then
|
||||
strInfo = string.format("Manifest file: %d%%", percent)
|
||||
else
|
||||
strInfo = string.format("%d%%", percent)
|
||||
end
|
||||
progress:setString(strInfo)
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST or
|
||||
eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST then
|
||||
print("Fail to download manifest file, update skipped.")
|
||||
local background = cc.Sprite:create("Images/background3.png")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE or
|
||||
eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then
|
||||
print("Update finished.")
|
||||
local background = cc.Sprite:create("Images/background3.png")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_UPDATING then
|
||||
print("Asset ", event:getAssetId(), ", ", event:getMessage())
|
||||
local background = cc.Sprite:create("Images/background3.png")
|
||||
layer:addChild(background, 1)
|
||||
background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y ))
|
||||
end
|
||||
end
|
||||
local listener = cc.EventListenerAssetsManagerEx:create(am,onUpdateEvent)
|
||||
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(listener, 1)
|
||||
|
||||
am:update()
|
||||
end
|
||||
end
|
||||
|
||||
local function onNodeEvent(event)
|
||||
if "enter" == event then
|
||||
onEnter()
|
||||
elseif "exit" == event then
|
||||
am:release()
|
||||
end
|
||||
end
|
||||
layer:registerScriptHandler(onNodeEvent)
|
||||
|
||||
return layer
|
||||
end
|
||||
|
||||
-------------------------------------
|
||||
-- AssetsManagerEx Test
|
||||
-------------------------------------
|
||||
function AssetsManagerExTestMain()
|
||||
local scene = cc.Scene:create()
|
||||
|
||||
Helper.createFunctionTable =
|
||||
{
|
||||
AMTestScene1.create,
|
||||
AMTestScene2.create,
|
||||
AMTestScene3.create,
|
||||
}
|
||||
|
||||
scene:addChild(AMTestScene1.create())
|
||||
scene:addChild(CreateBackMenuItem())
|
||||
return scene
|
||||
end
|
|
@ -1,160 +0,0 @@
|
|||
local targetPlatform = cc.Application:getInstance():getTargetPlatform()
|
||||
|
||||
local lineSpace = 40
|
||||
local itemTagBasic = 1000
|
||||
local menuItemNames =
|
||||
{
|
||||
"enter",
|
||||
"reset",
|
||||
"update",
|
||||
}
|
||||
|
||||
local winSize = cc.Director:getInstance():getWinSize()
|
||||
|
||||
local function updateLayer()
|
||||
local layer = cc.Layer:create()
|
||||
|
||||
local support = false
|
||||
if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform)
|
||||
or (cc.PLATFORM_OS_WINDOWS == targetPlatform) or (cc.PLATFORM_OS_ANDROID == targetPlatform)
|
||||
or (cc.PLATFORM_OS_MAC == targetPlatform) then
|
||||
support = true
|
||||
end
|
||||
|
||||
if not support then
|
||||
print("Platform is not supported!")
|
||||
return layer
|
||||
end
|
||||
|
||||
local isUpdateItemClicked = false
|
||||
local assetsManager = nil
|
||||
local pathToSave = ""
|
||||
|
||||
local menu = cc.Menu:create()
|
||||
menu:setPosition(cc.p(0, 0))
|
||||
cc.MenuItemFont:setFontName("Arial")
|
||||
cc.MenuItemFont:setFontSize(24)
|
||||
|
||||
local progressLable = cc.Label:createWithTTF("",s_arialPath,30)
|
||||
progressLable:setAnchorPoint(cc.p(0.5, 0.5))
|
||||
progressLable:setPosition(cc.p(140,50))
|
||||
layer:addChild(progressLable)
|
||||
|
||||
pathToSave = createDownloadDir()
|
||||
|
||||
local function onError(errorCode)
|
||||
if errorCode == cc.ASSETSMANAGER_NO_NEW_VERSION then
|
||||
progressLable:setString("no new version")
|
||||
elseif errorCode == cc.ASSETSMANAGER_NETWORK then
|
||||
progressLable:setString("network error")
|
||||
end
|
||||
end
|
||||
|
||||
local function onProgress( percent )
|
||||
local progress = string.format("downloading %d%%",percent)
|
||||
progressLable:setString(progress)
|
||||
end
|
||||
|
||||
local function onSuccess()
|
||||
progressLable:setString("downloading ok")
|
||||
end
|
||||
|
||||
local function getAssetsManager()
|
||||
if nil == assetsManager then
|
||||
assetsManager = cc.AssetsManager:new("https://raw.github.com/samuele3hu/AssetsManagerTest/master/package.zip",
|
||||
"https://raw.github.com/samuele3hu/AssetsManagerTest/master/version",
|
||||
pathToSave)
|
||||
assetsManager:retain()
|
||||
assetsManager:setDelegate(onError, cc.ASSETSMANAGER_PROTOCOL_ERROR )
|
||||
assetsManager:setDelegate(onProgress, cc.ASSETSMANAGER_PROTOCOL_PROGRESS)
|
||||
assetsManager:setDelegate(onSuccess, cc.ASSETSMANAGER_PROTOCOL_SUCCESS )
|
||||
assetsManager:setConnectionTimeout(3)
|
||||
end
|
||||
|
||||
return assetsManager
|
||||
end
|
||||
|
||||
local function update(sender)
|
||||
progressLable:setString("")
|
||||
|
||||
getAssetsManager():update()
|
||||
end
|
||||
|
||||
local function reset(sender)
|
||||
progressLable:setString("")
|
||||
|
||||
deleteDownloadDir(pathToSave)
|
||||
|
||||
getAssetsManager():deleteVersion()
|
||||
|
||||
createDownloadDir()
|
||||
end
|
||||
|
||||
local function reloadModule( moduleName )
|
||||
|
||||
package.loaded[moduleName] = nil
|
||||
|
||||
return require(moduleName)
|
||||
end
|
||||
|
||||
local function enter(sender)
|
||||
|
||||
if not isUpdateItemClicked then
|
||||
local realPath = pathToSave .. "/package"
|
||||
addSearchPath(realPath,true)
|
||||
end
|
||||
|
||||
assetsManagerModule = reloadModule("src/AssetsManagerTest/AssetsManagerModule")
|
||||
|
||||
assetsManagerModule.newScene(AssetsManagerTestMain)
|
||||
end
|
||||
|
||||
local callbackFuncs =
|
||||
{
|
||||
enter,
|
||||
reset,
|
||||
update,
|
||||
}
|
||||
|
||||
local function menuCallback(tag, menuItem)
|
||||
local scene = nil
|
||||
local nIdx = menuItem:getLocalZOrder() - itemTagBasic
|
||||
local ExtensionsTestScene = CreateExtensionsTestScene(nIdx)
|
||||
if nil ~= ExtensionsTestScene then
|
||||
cc.Director:getInstance():replaceScene(ExtensionsTestScene)
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, table.getn(menuItemNames) do
|
||||
local item = cc.MenuItemFont:create(menuItemNames[i])
|
||||
item:registerScriptTapHandler(callbackFuncs[i])
|
||||
item:setPosition(winSize.width / 2, winSize.height - i * lineSpace)
|
||||
if not support then
|
||||
item:setEnabled(false)
|
||||
end
|
||||
menu:addChild(item, itemTagBasic + i)
|
||||
end
|
||||
|
||||
local function onNodeEvent(msgName)
|
||||
if nil ~= assetsManager then
|
||||
assetsManager:release()
|
||||
assetsManager = nil
|
||||
end
|
||||
end
|
||||
|
||||
layer:registerScriptHandler(onNodeEvent)
|
||||
|
||||
layer:addChild(menu)
|
||||
|
||||
return layer
|
||||
end
|
||||
|
||||
-------------------------------------
|
||||
-- AssetsManager Test
|
||||
-------------------------------------
|
||||
function AssetsManagerTestMain()
|
||||
local scene = cc.Scene:create()
|
||||
scene:addChild(updateLayer())
|
||||
scene:addChild(CreateBackMenuItem())
|
||||
return scene
|
||||
end
|
|
@ -14,6 +14,7 @@ require "src/ActionManagerTest/ActionManagerTest"
|
|||
require "src/ActionsEaseTest/ActionsEaseTest"
|
||||
require "src/ActionsProgressTest/ActionsProgressTest"
|
||||
require "src/ActionsTest/ActionsTest"
|
||||
require "src/AssetsManagerExTest/AssetsManagerExTest"
|
||||
require "src/AssetsManagerTest/AssetsManagerTest"
|
||||
require "src/BillBoardTest/BillBoardTest"
|
||||
require "src/BugsTest/BugsTest"
|
||||
|
@ -78,6 +79,7 @@ local _allTests = {
|
|||
{ isSupported = true, name = "ActionsEaseTest" , create_func = EaseActionsTest },
|
||||
{ isSupported = true, name = "ActionsProgressTest" , create_func = ProgressActionsTest },
|
||||
{ isSupported = true, name = "ActionsTest" , create_func = ActionsTest },
|
||||
{ isSupported = true, name = "AssetsManagerExTest" , create_func = AssetsManagerExTestMain },
|
||||
{ isSupported = true, name = "AssetsManagerTest" , create_func = AssetsManagerTestMain },
|
||||
{ isSupported = audioEndineSupported, name = "AudioEngineTest", create_func = AudioEngineTest},
|
||||
{ isSupported = false, name = "Box2dTest" , create_func= Box2dTestMain },
|
||||
|
|
|
@ -13,7 +13,7 @@ android_flags = -D_SIZE_T_DEFINED_
|
|||
clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include
|
||||
clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__
|
||||
|
||||
cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android
|
||||
cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android -I%(cocosdir)s/external -I%(cocosdir)s/external/json
|
||||
|
||||
cocos_flags = -DANDROID
|
||||
|
||||
|
@ -27,7 +27,7 @@ headers = %(cocosdir)s/extensions/cocos-ext.h
|
|||
|
||||
# what classes to produce code for. You can use regular expressions here. When testing the regular
|
||||
# expression, it will be enclosed in "^$", like this: "^Menu*$".
|
||||
classes = AssetsManager.* Control.* ControlButton.* ScrollView$ TableView$ TableViewCell$
|
||||
classes = Control.* ControlButton.* ScrollView$ TableView$ TableViewCell$ AssetsManager Manifest EventAssetsManager EventListenerAssetsManager
|
||||
|
||||
# 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
|
||||
|
@ -39,13 +39,14 @@ classes = AssetsManager.* Control.* ControlButton.* ScrollView$ TableView$ Tabl
|
|||
skip = .*Delegate::[*],
|
||||
.*Loader.*::[*],
|
||||
*::[^visit$ copyWith.* onEnter.* onExit.* ^description$ getObjectType (g|s)etDelegate .*HSV],
|
||||
AssetsManager::[(g|s)etDelegate],
|
||||
AssetsManagerDelegateProtocol::[*],
|
||||
EditBox::[(g|s)etDelegate ^keyboard.* touchDownAction getScriptEditBoxHandler registerScriptEditBoxHandler unregisterScriptEditBoxHandler],
|
||||
Control::[removeHandleOfControlEvent addHandleOfControlEvent],
|
||||
ControlUtils::[*],
|
||||
ControlSwitchSprite::[*],
|
||||
ScrollView::[(g|s)etDelegate$],
|
||||
TableView::[create (g|s)etDataSource$ (g|s)etDelegate]
|
||||
TableView::[create (g|s)etDataSource$ (g|s)etDelegate],
|
||||
Manifest::[getAssets getAsset],
|
||||
EventListenerAssetsManager::[create]
|
||||
|
||||
|
||||
rename_functions =
|
||||
|
@ -63,7 +64,7 @@ base_classes_to_skip =
|
|||
|
||||
# classes that create no constructor
|
||||
# Set is special and we will use a hand-written constructor
|
||||
abstract_classes =
|
||||
abstract_classes = ArmatureDataManager Manifest
|
||||
|
||||
# Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'.
|
||||
script_control_cpp = no
|
||||
|
|
Loading…
Reference in New Issue