Merge branch 'v3' into v3FrameBufferObject

This commit is contained in:
Huabing.Xu 2015-05-25 16:56:22 +08:00
commit c22a8e81ce
724 changed files with 40043 additions and 12308 deletions

1
.gitignore vendored
View File

@ -116,6 +116,7 @@ tests/*/publish/
# Android
project.properties
*.iml
# Ignore prebuilt libraries folder
/external/*

View File

@ -1124,6 +1124,9 @@ Developers:
Fixed memory leak of WebView on iOS
Fixed crahed that if url contains illegal characters on Android
tankorsmash
Fixed the bug that ProgressTimer::setSprite() doesn't take effect
Retired Core Developers:
WenSheng Yang
Author of windows port, CCTextField,

View File

@ -1,20 +1,28 @@
cocos2d-x-3.7 ??
[NEW] 3rd: updated rapidjson to v1.0.2
[NEW] 3d: added physics3d support
[NEW] Audio: added support on WP8.1, now it supports wav format
[NEW] C++: added ActionFloat
[NEW] C++: support physical keyboard on WinRT
[NEW] FileUtils: checked filename case characters on windows
[NEW] FileUitls: added supporting loading files that which file path include utf-8 characters
[NEW] PhysicsShape: added sensor property
[NEW] Scale9Sprite: added Android 9-patch image support
[FIX] 3rd: fix PIE link error on iOS caused by libpng and libtiff
[FIX] AssetsManager: crashed issue
[FIX] Audio: can not play large ogg files on windows
[FIX] EaseRateAction: no way to create an `EaseRateAction` instance
[FIX] Label: crashed if invoking `setString(text` after `getLetter(letterIndex)` and `letterIndex` is greater than the length of text
[FIX] Label: position is wrong if label content is changed after invoking `getLetter(letterIndex)`
[FIX] Label: shadow effect cause OpenGL error on iOS
[FIX] Label: outline effect doesn't match characters well
[FIX] ProgressTimer: `setSprite()` doesn't take effect
[FIX] Sprite3D: setGLProgram() does not work
[FIX] Sprite3D: transition breaks when there is a Sprite3D in the scene
[FIX] Terrain: terrain is on top of particles, particles can not be seen
[FIX] TextureCache: unbindImageAsync failed to unbind all asynchronous callback for a specified bound image
[FIX] TileMap: crashed if a layer contains nothing
[FIX] WebView: memory leak on iOS
[FIX] WebView: crashed if url contains illegal characters on Android

View File

@ -186,7 +186,7 @@ $ bin/lua-empty-test/lua-empty-test
* For Windows
Open the `cocos2d-x/build/cocos2d-win32.vc2013.sln`
Open the `cocos2d-x/build/cocos2d-win32.sln`
* For Windows 8.1 Universal Apps (Phone and Store)

View File

@ -45,6 +45,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libjscocos2d.Windows", "..\
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libjscocos2d.WindowsPhone", "..\cocos\scripting\js-bindings\proj.win8.1-universal\libjscocos2d\libjscocos2d.WindowsPhone\libjscocos2d.WindowsPhone.vcxproj", "{CA082EC4-17CE-430B-8207-D1E947A5D1E9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "libbullet", "libbullet", "{9A66AB4C-057B-4675-849D-5D69B98C728C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbullet.Shared", "..\external\bullet\proj.win8.1-universal\libbullet.Shared\libbullet.Shared.vcxitems", "{16AF311F-74CA-45A3-A82D-6334200FB124}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbullet.Windows", "..\external\bullet\proj.win8.1-universal\libbullet.Windows\libbullet.Windows.vcxproj", "{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbullet.WindowsPhone", "..\external\bullet\proj.win8.1-universal\libbullet.WindowsPhone\libbullet.WindowsPhone.vcxproj", "{E35634BD-B91B-4A6D-B957-96F56DD065F9}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\tests\js-tests\project\proj.win8.1-universal\App.Shared\js-tests.Shared.vcxitems*{ae6763f6-1549-441e-afb5-377be1c776dc}*SharedItemsImports = 9
@ -53,7 +61,10 @@ Global
..\tests\js-tests\project\proj.win8.1-universal\App.Shared\js-tests.Shared.vcxitems*{70914fc8-7709-4cd6-b86b-c63fde5478db}*SharedItemsImports = 4
..\cocos\editor-support\spine\proj.win8.1-universal\libSpine.Shared\libSpine.Shared.vcxitems*{cc1da216-a80d-4be4-b309-acb6af313aff}*SharedItemsImports = 4
..\external\Box2D\proj.win8.1-universal\libbox2d.Shared\libbox2d.Shared.vcxitems*{4a3c6ba8-c227-498b-aa21-40bda27b461f}*SharedItemsImports = 9
..\external\bullet\proj.win8.1-universal\libbullet.Shared\libbullet.Shared.vcxitems*{e35634bd-b91b-4a6d-b957-96f56dd065f9}*SharedItemsImports = 4
..\external\bullet\proj.win8.1-universal\libbullet.Shared\libbullet.Shared.vcxitems*{ec2b1292-2d8c-4feb-a84b-2550b32c1ae7}*SharedItemsImports = 4
..\cocos\editor-support\spine\proj.win8.1-universal\libSpine.Shared\libSpine.Shared.vcxitems*{adafd00d-a0d6-46ef-9f0b-ea2880bfe1de}*SharedItemsImports = 9
..\external\bullet\proj.win8.1-universal\libbullet.Shared\libbullet.Shared.vcxitems*{16af311f-74ca-45a3-a82d-6334200fb124}*SharedItemsImports = 9
..\cocos\scripting\js-bindings\proj.win8.1-universal\libjscocos2d\libjscocos2d.Shared\libjscocos2d.Shared.vcxitems*{ca082ec4-17ce-430b-8207-d1e947a5d1e9}*SharedItemsImports = 4
..\cocos\2d\libcocos2d_8_1\libcocos2d_8_1\libcocos2d_8_1.Shared\libcocos2d_8_1.Shared.vcxitems*{5d6f020f-7e72-4494-90a0-2df11d235df9}*SharedItemsImports = 9
..\cocos\scripting\js-bindings\proj.win8.1-universal\libjscocos2d\libjscocos2d.Shared\libjscocos2d.Shared.vcxitems*{bea66276-51dd-4c53-92a8-f3d1fea50892}*SharedItemsImports = 9
@ -192,6 +203,28 @@ Global
{CA082EC4-17CE-430B-8207-D1E947A5D1E9}.Release|Win32.ActiveCfg = Release|Win32
{CA082EC4-17CE-430B-8207-D1E947A5D1E9}.Release|Win32.Build.0 = Release|Win32
{CA082EC4-17CE-430B-8207-D1E947A5D1E9}.Release|x64.ActiveCfg = Release|Win32
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|ARM.ActiveCfg = Debug|ARM
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|ARM.Build.0 = Debug|ARM
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|Win32.ActiveCfg = Debug|Win32
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|Win32.Build.0 = Debug|Win32
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|x64.ActiveCfg = Debug|x64
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|x64.Build.0 = Debug|x64
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|ARM.ActiveCfg = Release|ARM
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|ARM.Build.0 = Release|ARM
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|Win32.ActiveCfg = Release|Win32
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|Win32.Build.0 = Release|Win32
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|x64.ActiveCfg = Release|x64
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|x64.Build.0 = Release|x64
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Debug|ARM.ActiveCfg = Debug|ARM
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Debug|ARM.Build.0 = Debug|ARM
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Debug|Win32.ActiveCfg = Debug|Win32
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Debug|Win32.Build.0 = Debug|Win32
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Debug|x64.ActiveCfg = Debug|Win32
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Release|ARM.ActiveCfg = Release|ARM
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Release|ARM.Build.0 = Release|ARM
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Release|Win32.ActiveCfg = Release|Win32
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Release|Win32.Build.0 = Release|Win32
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -214,5 +247,9 @@ Global
{BEA66276-51DD-4C53-92A8-F3D1FEA50892} = {60DCAEA9-E344-40C0-B90C-82FB8E671BD5}
{BCF5546D-66A0-4998-AFD6-C5514F618930} = {60DCAEA9-E344-40C0-B90C-82FB8E671BD5}
{CA082EC4-17CE-430B-8207-D1E947A5D1E9} = {60DCAEA9-E344-40C0-B90C-82FB8E671BD5}
{9A66AB4C-057B-4675-849D-5D69B98C728C} = {85630454-74EA-4B5B-9B62-0E459B4476CB}
{16AF311F-74CA-45A3-A82D-6334200FB124} = {9A66AB4C-057B-4675-849D-5D69B98C728C}
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7} = {9A66AB4C-057B-4675-849D-5D69B98C728C}
{E35634BD-B91B-4A6D-B957-96F56DD065F9} = {9A66AB4C-057B-4675-849D-5D69B98C728C}
EndGlobalSection
EndGlobal

View File

@ -45,6 +45,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelloCpp.Windows", "..\test
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelloCpp.WindowsPhone", "..\tests\cpp-empty-test\proj.win8.1-universal\HelloCpp.WindowsPhone\HelloCpp.WindowsPhone.vcxproj", "{396FE85E-BB05-4B92-BCCB-F89AED4EA41A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "libbullet", "libbullet", "{0500043C-7E95-4351-97D6-0382A8C92DD3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbullet.Shared", "..\external\bullet\proj.win8.1-universal\libbullet.Shared\libbullet.Shared.vcxitems", "{16AF311F-74CA-45A3-A82D-6334200FB124}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbullet.Windows", "..\external\bullet\proj.win8.1-universal\libbullet.Windows\libbullet.Windows.vcxproj", "{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbullet.WindowsPhone", "..\external\bullet\proj.win8.1-universal\libbullet.WindowsPhone\libbullet.WindowsPhone.vcxproj", "{E35634BD-B91B-4A6D-B957-96F56DD065F9}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\cocos\2d\libcocos2d_8_1\libcocos2d_8_1\libcocos2d_8_1.Shared\libcocos2d_8_1.Shared.vcxitems*{9335005f-678e-4e8e-9b84-50037216aec8}*SharedItemsImports = 4
@ -52,9 +60,12 @@ Global
..\tests\cpp-empty-test\proj.win8.1-universal\HelloCpp.Shared\HelloCpp.Shared.vcxitems*{a3ad93e4-0b2f-4c58-9181-69bed2e42e3e}*SharedItemsImports = 9
..\cocos\editor-support\spine\proj.win8.1-universal\libSpine.Shared\libSpine.Shared.vcxitems*{cc1da216-a80d-4be4-b309-acb6af313aff}*SharedItemsImports = 4
..\external\Box2D\proj.win8.1-universal\libbox2d.Shared\libbox2d.Shared.vcxitems*{4a3c6ba8-c227-498b-aa21-40bda27b461f}*SharedItemsImports = 9
..\external\bullet\proj.win8.1-universal\libbullet.Shared\libbullet.Shared.vcxitems*{e35634bd-b91b-4a6d-b957-96f56dd065f9}*SharedItemsImports = 4
..\tests\cpp-empty-test\proj.win8.1-universal\HelloCpp.Shared\HelloCpp.Shared.vcxitems*{79a8fcda-4b12-4dd1-b676-ff148d651638}*SharedItemsImports = 4
..\external\bullet\proj.win8.1-universal\libbullet.Shared\libbullet.Shared.vcxitems*{ec2b1292-2d8c-4feb-a84b-2550b32c1ae7}*SharedItemsImports = 4
..\cocos\editor-support\spine\proj.win8.1-universal\libSpine.Shared\libSpine.Shared.vcxitems*{adafd00d-a0d6-46ef-9f0b-ea2880bfe1de}*SharedItemsImports = 9
..\tests\cpp-tests\proj.win8.1-universal\cpp-tests.Shared\cpp-tests.Shared.vcxitems*{be3a1791-5bce-4cea-92cd-0e2d86dde27a}*SharedItemsImports = 9
..\external\bullet\proj.win8.1-universal\libbullet.Shared\libbullet.Shared.vcxitems*{16af311f-74ca-45a3-a82d-6334200fb124}*SharedItemsImports = 9
..\cocos\2d\libcocos2d_8_1\libcocos2d_8_1\libcocos2d_8_1.Shared\libcocos2d_8_1.Shared.vcxitems*{5d6f020f-7e72-4494-90a0-2df11d235df9}*SharedItemsImports = 9
..\external\Box2D\proj.win8.1-universal\libbox2d.Shared\libbox2d.Shared.vcxitems*{3b26a12d-3a44-47ea-82d2-282660fc844d}*SharedItemsImports = 4
..\cocos\2d\libcocos2d_8_1\libcocos2d_8_1\libcocos2d_8_1.Shared\libcocos2d_8_1.Shared.vcxitems*{22f3b9df-1209-4574-8331-003966f562bf}*SharedItemsImports = 4
@ -202,6 +213,28 @@ Global
{396FE85E-BB05-4B92-BCCB-F89AED4EA41A}.Release|Win32.Build.0 = Release|Win32
{396FE85E-BB05-4B92-BCCB-F89AED4EA41A}.Release|Win32.Deploy.0 = Release|Win32
{396FE85E-BB05-4B92-BCCB-F89AED4EA41A}.Release|x64.ActiveCfg = Release|Win32
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|ARM.ActiveCfg = Debug|ARM
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|ARM.Build.0 = Debug|ARM
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|Win32.ActiveCfg = Debug|Win32
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|Win32.Build.0 = Debug|Win32
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|x64.ActiveCfg = Debug|x64
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Debug|x64.Build.0 = Debug|x64
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|ARM.ActiveCfg = Release|ARM
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|ARM.Build.0 = Release|ARM
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|Win32.ActiveCfg = Release|Win32
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|Win32.Build.0 = Release|Win32
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|x64.ActiveCfg = Release|x64
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7}.Release|x64.Build.0 = Release|x64
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Debug|ARM.ActiveCfg = Debug|ARM
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Debug|ARM.Build.0 = Debug|ARM
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Debug|Win32.ActiveCfg = Debug|Win32
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Debug|Win32.Build.0 = Debug|Win32
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Debug|x64.ActiveCfg = Debug|Win32
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Release|ARM.ActiveCfg = Release|ARM
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Release|ARM.Build.0 = Release|ARM
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Release|Win32.ActiveCfg = Release|Win32
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Release|Win32.Build.0 = Release|Win32
{E35634BD-B91B-4A6D-B957-96F56DD065F9}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -224,5 +257,9 @@ Global
{A3AD93E4-0B2F-4C58-9181-69BED2E42E3E} = {B70EF25E-E352-4020-BCDF-388973E44637}
{79A8FCDA-4B12-4DD1-B676-FF148D651638} = {B70EF25E-E352-4020-BCDF-388973E44637}
{396FE85E-BB05-4B92-BCCB-F89AED4EA41A} = {B70EF25E-E352-4020-BCDF-388973E44637}
{0500043C-7E95-4351-97D6-0382A8C92DD3} = {85630454-74EA-4B5B-9B62-0E459B4476CB}
{16AF311F-74CA-45A3-A82D-6334200FB124} = {0500043C-7E95-4351-97D6-0382A8C92DD3}
{EC2B1292-2D8C-4FEB-A84B-2550B32C1AE7} = {0500043C-7E95-4351-97D6-0382A8C92DD3}
{E35634BD-B91B-4A6D-B957-96F56DD065F9} = {0500043C-7E95-4351-97D6-0382A8C92DD3}
EndGlobalSection
EndGlobal

View File

@ -821,7 +821,7 @@
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/.. $(SRCROOT)/../cocos $(SRCROOT)/../cocos/base $(SRCROOT)/../cocos/physics $(SRCROOT)/../cocos/math/kazmath $(SRCROOT)/../cocos/2d $(SRCROOT)/../cocos/gui $(SRCROOT)/../cocos/network $(SRCROOT)/../cocos/audio/include $(SRCROOT)/../cocos/editor-support $(SRCROOT)/../extensions $(SRCROOT)/../external $(SRCROOT)/../external/chipmunk/include/chipmunk $(SRCROOT)/../cocos/scripting/js-bindings/auto $(SRCROOT)/../cocos/scripting/js-bindings/manual";
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/.. $(SRCROOT)/../cocos $(SRCROOT)/../cocos/base $(SRCROOT)/../cocos/2d $(SRCROOT)/../cocos/gui $(SRCROOT)/../cocos/network $(SRCROOT)/../cocos/audio/include $(SRCROOT)/../cocos/editor-support $(SRCROOT)/../extensions $(SRCROOT)/../external $(SRCROOT)/../external/chipmunk/include/chipmunk $(SRCROOT)/../cocos/scripting/js-bindings/auto $(SRCROOT)/../cocos/scripting/js-bindings/manual";
};
name = Debug;
};
@ -845,7 +845,7 @@
HEADER_SEARCH_PATHS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/.. $(SRCROOT)/../cocos $(SRCROOT)/../cocos/base $(SRCROOT)/../cocos/physics $(SRCROOT)/../cocos/math/kazmath $(SRCROOT)/../cocos/2d $(SRCROOT)/../cocos/gui $(SRCROOT)/../cocos/network $(SRCROOT)/../cocos/audio/include $(SRCROOT)/../cocos/editor-support $(SRCROOT)/../extensions $(SRCROOT)/../external $(SRCROOT)/../external/chipmunk/include/chipmunk $(SRCROOT)/../cocos/scripting/js-bindings/auto $(SRCROOT)/../cocos/scripting/js-bindings/manual";
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/.. $(SRCROOT)/../cocos $(SRCROOT)/../cocos/base $(SRCROOT)/../cocos/2d $(SRCROOT)/../cocos/gui $(SRCROOT)/../cocos/network $(SRCROOT)/../cocos/audio/include $(SRCROOT)/../cocos/editor-support $(SRCROOT)/../extensions $(SRCROOT)/../external $(SRCROOT)/../external/chipmunk/include/chipmunk $(SRCROOT)/../cocos/scripting/js-bindings/auto $(SRCROOT)/../cocos/scripting/js-bindings/manual";
};
name = Release;
};

View File

@ -1190,6 +1190,10 @@
1AC0269D1914068200FA920D /* ConvertUTF.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AC026991914068200FA920D /* ConvertUTF.h */; };
29031E0719BFE8D400EFA1DF /* libchipmunk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 29031E0619BFE8D400EFA1DF /* libchipmunk.a */; };
29031E0919BFE8DE00EFA1DF /* libchipmunk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 29031E0819BFE8DE00EFA1DF /* libchipmunk.a */; };
291901431B05895600F8B4BA /* CCNinePatchImageParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 291901411B05895600F8B4BA /* CCNinePatchImageParser.h */; };
291901441B05895600F8B4BA /* CCNinePatchImageParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 291901411B05895600F8B4BA /* CCNinePatchImageParser.h */; };
291901451B05895600F8B4BA /* CCNinePatchImageParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 291901421B05895600F8B4BA /* CCNinePatchImageParser.cpp */; };
291901461B05895600F8B4BA /* CCNinePatchImageParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 291901421B05895600F8B4BA /* CCNinePatchImageParser.cpp */; };
292DB13D19B4574100A80320 /* UIEditBox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 292DB12F19B4574100A80320 /* UIEditBox.cpp */; };
292DB13E19B4574100A80320 /* UIEditBox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 292DB12F19B4574100A80320 /* UIEditBox.cpp */; };
292DB13F19B4574100A80320 /* UIEditBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 292DB13019B4574100A80320 /* UIEditBox.h */; };
@ -3925,6 +3929,8 @@
2905FA1318CF08D100240AA3 /* UIWidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UIWidget.cpp; sourceTree = "<group>"; };
2905FA1418CF08D100240AA3 /* UIWidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIWidget.h; sourceTree = "<group>"; };
29080DEB191B82CE0066F8DF /* UIDeprecated.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIDeprecated.h; sourceTree = "<group>"; };
291901411B05895600F8B4BA /* CCNinePatchImageParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCNinePatchImageParser.h; path = ../base/CCNinePatchImageParser.h; sourceTree = "<group>"; };
291901421B05895600F8B4BA /* CCNinePatchImageParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CCNinePatchImageParser.cpp; path = ../base/CCNinePatchImageParser.cpp; sourceTree = "<group>"; };
292DB12F19B4574100A80320 /* UIEditBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UIEditBox.cpp; sourceTree = "<group>"; };
292DB13019B4574100A80320 /* UIEditBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIEditBox.h; sourceTree = "<group>"; };
292DB13119B4574100A80320 /* UIEditBoxImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIEditBoxImpl.h; sourceTree = "<group>"; };
@ -5626,6 +5632,8 @@
1A5700A2180BC5E60088DEC7 /* base */ = {
isa = PBXGroup;
children = (
291901411B05895600F8B4BA /* CCNinePatchImageParser.h */,
291901421B05895600F8B4BA /* CCNinePatchImageParser.cpp */,
505385001B01887A00793096 /* CCProperties.h */,
505385011B01887A00793096 /* CCProperties.cpp */,
B63990CA1A490AFE00B07923 /* CCAsyncTaskPool.cpp */,
@ -9417,6 +9425,7 @@
50ABBE211925AB6F00A911A9 /* atitc.h in Headers */,
15AE19A519AAD39600C27E9E /* TextFieldReader.h in Headers */,
B665E3401AA80A6500DDB1C5 /* CCPUOnEventFlagObserverTranslator.h in Headers */,
291901431B05895600F8B4BA /* CCNinePatchImageParser.h in Headers */,
B24AA98B195A675C007B4522 /* CCFastTMXTiledMap.h in Headers */,
B665E3A01AA80A6500DDB1C5 /* CCPUPositionEmitter.h in Headers */,
B29594B61926D5EC003EEF37 /* CCMeshCommand.h in Headers */,
@ -10220,6 +10229,7 @@
50ABBE481925AB6F00A911A9 /* CCEvent.h in Headers */,
5027253B190BF1B900AAF4ED /* cocos2d.h in Headers */,
15AE1A9719AAD40300C27E9E /* b2Draw.h in Headers */,
291901441B05895600F8B4BA /* CCNinePatchImageParser.h in Headers */,
3E6176691960F89B00DE83F5 /* CCController.h in Headers */,
B6CAB43E1AF9AA1A00B9B856 /* btGpuDefines.h in Headers */,
3823841D1A2590D2002C4610 /* ComAudioReader.h in Headers */,
@ -10693,6 +10703,7 @@
50ED2BD919BE5D5D00A0AB90 /* CCEventListenerController.cpp in Sources */,
B665E2321AA80A6500DDB1C5 /* CCPUBoxEmitter.cpp in Sources */,
B257B460198A353E00D9A687 /* CCPrimitiveCommand.cpp in Sources */,
291901451B05895600F8B4BA /* CCNinePatchImageParser.cpp in Sources */,
15AE19A419AAD39600C27E9E /* TextFieldReader.cpp in Sources */,
50ED2BDB19BE76D500A0AB90 /* UIVideoPlayer-ios.mm in Sources */,
B665E32A1AA80A6500DDB1C5 /* CCPUOnCountObserver.cpp in Sources */,
@ -11653,6 +11664,7 @@
15AE19AA19AAD39700C27E9E /* ListViewReader.cpp in Sources */,
1A5701C8180BCB5A0088DEC7 /* CCLabelTextFormatter.cpp in Sources */,
1A5701CC180BCB5A0088DEC7 /* CCLabelTTF.cpp in Sources */,
291901461B05895600F8B4BA /* CCNinePatchImageParser.cpp in Sources */,
B665E39B1AA80A6500DDB1C5 /* CCPUPointEmitterTranslator.cpp in Sources */,
382384291A2590F9002C4610 /* NodeReader.cpp in Sources */,
15AE193419AAD35100C27E9E /* CCActionObject.cpp in Sources */,

View File

@ -125,9 +125,9 @@ public:
* @param t Duration in seconds.
* @param radius The start radius.
* @param deltaRadius The delta radius.
* @param angleZ The start Angel in Z.
* @param angleZ The start angle in Z.
* @param deltaAngleZ The delta angle in Z.
* @param angleX The start Angel in X.
* @param angleX The start angle in X.
* @param deltaAngleX The delta angle in X.
* @return An OrbitCamera.
*/

View File

@ -118,7 +118,7 @@ public:
*
* @param center The circle center point.
* @param radius The circle rotate of radius.
* @param angle The circle angel.
* @param angle The circle angle.
* @param segments The number of segments.
* @param drawLineToCenter Whether or not draw the line from the origin to center.
* @param scaleX The scale value in x.
@ -131,7 +131,7 @@ public:
*
* @param center The circle center point.
* @param radius The circle rotate of radius.
* @param angle The circle angel.
* @param angle The circle angle.
* @param segments The number of segments.
* @param drawLineToCenter Whether or not draw the line from the origin to center.
* @param color Set the circle color.
@ -216,7 +216,7 @@ public:
/** Draws a solid circle given the center, radius and number of segments.
* @param center The circle center point.
* @param radius The circle rotate of radius.
* @param angle The circle angel.
* @param angle The circle angle.
* @param segments The number of segments.
* @param scaleX The scale value in x.
* @param scaleY The scale value in y.
@ -228,7 +228,7 @@ public:
/** Draws a solid circle given the center, radius and number of segments.
* @param center The circle center point.
* @param radius The circle rotate of radius.
* @param angle The circle angel.
* @param angle The circle angle.
* @param segments The number of segments.
* @param color The solid circle color.
* @js NA

View File

@ -153,7 +153,7 @@ namespace DrawPrimitives
*
* @param center The circle center point.
* @param radius The circle rotate of radius.
* @param angle The circle angel.
* @param angle The circle angle.
* @param segments The number of segments.
* @param drawLineToCenter Whether or not draw the line from the origin to center.
* @param scaleX The scale value in x.
@ -165,7 +165,7 @@ namespace DrawPrimitives
*
* @param center The circle center point.
* @param radius The circle rotate of radius.
* @param angle The circle angel.
* @param angle The circle angle.
* @param segments The number of segments.
* @param drawLineToCenter Whether or not draw the line from the origin to center.
*/
@ -174,7 +174,7 @@ namespace DrawPrimitives
/** Draws a solid circle given the center, radius and number of segments.
* @param center The circle center point.
* @param radius The circle rotate of radius.
* @param angle The circle angel.
* @param angle The circle angle.
* @param segments The number of segments.
* @param scaleX The scale value in x.
* @param scaleY The scale value in y.
@ -185,7 +185,7 @@ namespace DrawPrimitives
/** Draws a solid circle given the center, radius and number of segments.
* @param center The circle center point.
* @param radius The circle rotate of radius.
* @param angle The circle angel.
* @param angle The circle angle.
* @param segments The number of segments.
* @js NA
*/

View File

@ -101,6 +101,9 @@ TMXTiledMap::~TMXTiledMap()
TMXLayer * TMXTiledMap::parseLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
{
TMXTilesetInfo *tileset = tilesetForLayer(layerInfo, mapInfo);
if (tileset == nullptr)
return nullptr;
TMXLayer *layer = TMXLayer::create(tileset, layerInfo, mapInfo);
// tell the layerinfo to release the ownership of the tiles map.
@ -170,6 +173,10 @@ void TMXTiledMap::buildWithMapInfo(TMXMapInfo* mapInfo)
if (layerInfo->_visible)
{
TMXLayer *child = parseLayer(layerInfo, mapInfo);
if (child == nullptr) {
idx++;
continue;
}
addChild(child, idx, idx);
// update content size with the max size

View File

@ -1315,8 +1315,11 @@ uint32_t Node::processParentFlags(const Mat4& parentTransform, uint32_t parentFl
}
}
if (!isVisitableByVisitingCamera())
return parentFlags;
//remove this two line given that isVisitableByVisitingCamera should not affect the calculation of transform given that we are visiting scene
//without involving view and projection matrix.
// if (!isVisitableByVisitingCamera())
// return parentFlags;
uint32_t flags = parentFlags;
flags |= (_transformUpdated ? FLAGS_TRANSFORM_DIRTY : 0);

View File

@ -115,6 +115,8 @@ void ProgressTimer::setSprite(Sprite *sprite)
CC_SAFE_FREE(_vertexData);
_vertexDataCount = 0;
}
updateProgress();
}
}

View File

@ -598,8 +598,8 @@ void Sprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
if(_insideBounds)
#endif
{
_quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, transform, flags);
renderer->addCommand(&_quadCommand);
_trianglesCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, getRenderedTriangles(), transform, flags);
renderer->addCommand(&_trianglesCommand);
#if CC_SPRITE_DEBUG_DRAW
_debugDrawNode->clear();
@ -614,6 +614,17 @@ void Sprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
}
}
TrianglesCommand::Triangles Sprite::getRenderedTriangles() const
{
static unsigned short indices[6] = {0, 1, 2, 3, 2, 1};
TrianglesCommand::Triangles result;
result.indices = indices;
result.verts = (V3F_C4B_T2F*)&_quad;
result.vertCount = 4;
result.indexCount = 6;
return result;
}
// MARK: visit, draw, transform
void Sprite::addChild(Node *child, int zOrder, int tag)
@ -993,6 +1004,10 @@ bool Sprite::isFrameDisplayed(SpriteFrame *frame) const
SpriteFrame* Sprite::getSpriteFrame() const
{
if(nullptr != this->_spriteFrame)
{
return this->_spriteFrame;
}
return SpriteFrame::createWithTexture(_texture,
CC_RECT_POINTS_TO_PIXELS(_rect),
_rectRotated,

View File

@ -33,7 +33,7 @@ THE SOFTWARE.
#include "2d/CCDrawNode.h"
#include "base/CCProtocols.h"
#include "renderer/CCTextureAtlas.h"
#include "renderer/CCQuadCommand.h"
#include "renderer/CCTrianglesCommand.h"
#include "renderer/CCCustomCommand.h"
NS_CC_BEGIN
@ -539,6 +539,7 @@ protected:
virtual void setReorderChildDirtyRecursively();
virtual void setDirtyRecursively(bool value);
TrianglesCommand::Triangles getRenderedTriangles() const;
//
// Data used when the sprite is rendered using a SpriteSheet
//
@ -557,7 +558,7 @@ protected:
BlendFunc _blendFunc; /// It's required for TextureProtocol inheritance
Texture2D* _texture; /// Texture2D object that is used to render the sprite
SpriteFrame* _spriteFrame;
QuadCommand _quadCommand; /// quad command
TrianglesCommand _trianglesCommand; ///
#if CC_SPRITE_DEBUG_DRAW
DrawNode *_debugDrawNode;
#endif //CC_SPRITE_DEBUG_DRAW

View File

@ -39,7 +39,7 @@ THE SOFTWARE.
#include "base/CCDirector.h"
#include "renderer/CCTexture2D.h"
#include "renderer/CCTextureCache.h"
#include "base/CCNinePatchImageParser.h"
#include "deprecated/CCString.h"
@ -104,6 +104,10 @@ void SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dictionary, Textu
// check the format
CCASSERT(format >=0 && format <= 3, "format is not supported for SpriteFrameCache addSpriteFramesWithDictionary:textureFilename:");
auto textureFileName = Director::getInstance()->getTextureCache()->getTextureFilePath(texture);
auto image = new Image();
image->initWithImageFile(textureFileName);
NinePatchImageParser parser(image);
for (auto iter = framesDict.begin(); iter != framesDict.end(); ++iter)
{
ValueMap& frameDict = iter->second.asValueMap();
@ -192,9 +196,16 @@ void SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dictionary, Textu
spriteSourceSize);
}
bool flag = NinePatchImageParser::isNinePatchImage(spriteFrameName);
if(flag)
{
parser.setSpriteFrameInfo(spriteFrame->getRectInPixels(), spriteFrame->isRotated());
texture->addSpriteFrameCapInset(spriteFrame, parser.parseCapInset());
}
// add sprite frame
_spriteFrames.insert(spriteFrameName, spriteFrame);
}
CC_SAFE_DELETE(image);
}
void SpriteFrameCache::addSpriteFramesWithFile(const std::string& plist, Texture2D *texture)
@ -327,6 +338,7 @@ void SpriteFrameCache::removeUnusedSpriteFrames()
if( spriteFrame->getReferenceCount() == 1 )
{
toRemoveFrames.push_back(iter->first);
spriteFrame->getTexture()->removeSpriteFrameCapInset(spriteFrame);
CCLOG("cocos2d: SpriteFrameCache: removing unused frame: %s", iter->first.c_str());
removed = true;
}

View File

@ -102,6 +102,9 @@ TMXTiledMap::~TMXTiledMap()
TMXLayer * TMXTiledMap::parseLayer(TMXLayerInfo *layerInfo, TMXMapInfo *mapInfo)
{
TMXTilesetInfo *tileset = tilesetForLayer(layerInfo, mapInfo);
if (tileset == nullptr)
return nullptr;
TMXLayer *layer = TMXLayer::create(tileset, layerInfo, mapInfo);
// tell the layerinfo to release the ownership of the tiles map.
@ -171,9 +174,12 @@ void TMXTiledMap::buildWithMapInfo(TMXMapInfo* mapInfo)
auto& layers = mapInfo->getLayers();
for(const auto &layerInfo : layers) {
if (layerInfo->_visible)
{
if (layerInfo->_visible) {
TMXLayer *child = parseLayer(layerInfo, mapInfo);
if (child == nullptr) {
idx++;
continue;
}
addChild(child, idx, idx);
// update content size with the max size

View File

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>opengl32.lib;glew32.lib;libzlib.lib;libpng.lib;libjpeg.lib;libtiff.lib;libwebp.lib;libiconv.lib;glfw3.lib;freetype250.lib;winmm.lib;ws2_32.lib;libchipmunk.lib;libbox2d.lib;libSpine.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>opengl32.lib;glew32.lib;libzlib.lib;libwebp.lib;libiconv.lib;freetype250.lib;winmm.lib;ws2_32.lib;libbox2d.lib;libSpine.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
</Link>

View File

@ -432,6 +432,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.*
<ClCompile Include="..\base\CCEventTouch.cpp" />
<ClCompile Include="..\base\ccFPSImages.c" />
<ClCompile Include="..\base\CCIMEDispatcher.cpp" />
<ClCompile Include="..\base\CCNinePatchImageParser.cpp" />
<ClCompile Include="..\base\CCNS.cpp" />
<ClCompile Include="..\base\CCProfiling.cpp" />
<ClCompile Include="..\base\CCProperties.cpp" />
@ -995,6 +996,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.*
<ClInclude Include="..\base\CCIMEDispatcher.h" />
<ClInclude Include="..\base\ccMacros.h" />
<ClInclude Include="..\base\CCMap.h" />
<ClInclude Include="..\base\CCNinePatchImageParser.h" />
<ClInclude Include="..\base\CCNS.h" />
<ClInclude Include="..\base\CCProfiling.h" />
<ClInclude Include="..\base\CCProperties.h" />

View File

@ -1872,6 +1872,9 @@
<ClCompile Include="..\renderer\CCVertexAttribBinding.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\base\CCNinePatchImageParser.cpp">
<Filter>base</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\physics\CCPhysicsBody.h">
@ -3662,6 +3665,9 @@
<ClInclude Include="..\renderer\CCVertexAttribBinding.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\base\CCNinePatchImageParser.h">
<Filter>base</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\math\Mat4.inl">

View File

@ -236,6 +236,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\include\Export.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\include\SimpleAudioEngine.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\Audio.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioCachePlayer.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioEngine-winrt.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioSourceReader.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\MediaStreamer.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\allocator\CCAllocatorBase.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\allocator\CCAllocatorDiagnostics.h" />
@ -282,6 +285,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCIMEDispatcher.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\ccMacros.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCMap.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCNinePatchImageParser.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCNS.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCProfiling.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCProperties.h" />
@ -442,6 +446,14 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\network\HttpResponse.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\network\SocketIO.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\network\WebSocket.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3D.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DComponent.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DConstraint.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DDebugDrawer.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DObject.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DShape.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DWorld.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysicsSprite3D.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics\CCPhysicsBody.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics\CCPhysicsContact.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics\CCPhysicsHelper.h" />
@ -830,11 +842,15 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\3d\CCSprite3DMaterial.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\3d\CCTerrain.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\3d\CCTextureCube.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\AudioEngine.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\Audio.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<ForcedIncludeFiles>
</ForcedIncludeFiles>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioCachePlayer.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioEngine-winrt.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioSourceReader.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\MediaStreamer.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<ForcedIncludeFiles>
@ -883,6 +899,7 @@
</ForcedIncludeFiles>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCIMEDispatcher.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCNinePatchImageParser.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCNS.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCProfiling.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCProperties.cpp" />
@ -892,7 +909,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCScriptSupport.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCTouch.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\ccTypes.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCUserDefault.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCUserDefault-winrt.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\ccUTF8.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\ccUtils.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCValue.cpp" />
@ -1019,6 +1036,14 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\network\HttpClient.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\network\SocketIO.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\network\WebSocket.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3D.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DComponent.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DConstraint.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DDebugDrawer.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DObject.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DShape.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DWorld.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysicsSprite3D.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics\CCPhysicsBody.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics\CCPhysicsContact.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics\CCPhysicsJoint.cpp" />
@ -1222,4 +1247,7 @@
<None Include="$(MSBuildThisFileDirectory)..\..\..\libcocos2d.vcxproj.filters" />
<None Include="$(MSBuildThisFileDirectory)..\..\..\libcocos2d_wp8.vcxproj.filters" />
</ItemGroup>
<ItemGroup>
<Text Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CMakeLists.txt" />
</ItemGroup>
</Project>

View File

@ -1791,6 +1791,42 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\renderer\CCVertexAttribBinding.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3D.h">
<Filter>physics3d</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DComponent.h">
<Filter>physics3d</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DConstraint.h">
<Filter>physics3d</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DDebugDrawer.h">
<Filter>physics3d</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DObject.h">
<Filter>physics3d</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DShape.h">
<Filter>physics3d</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DWorld.h">
<Filter>physics3d</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysicsSprite3D.h">
<Filter>physics3d</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\include\AudioEngine.h">
<Filter>audioengine</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioCachePlayer.h">
<Filter>audioengine</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioEngine-winrt.h">
<Filter>audioengine</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioSourceReader.h">
<Filter>audioengine</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\cocos2d.cpp" />
@ -2776,9 +2812,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\ccTypes.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCUserDefault.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\ccUTF8.cpp">
<Filter>base</Filter>
</ClCompile>
@ -3405,6 +3438,45 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\renderer\CCVertexAttribBinding.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\AudioEngine.cpp">
<Filter>audioengine</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioCachePlayer.cpp">
<Filter>audioengine</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioEngine-winrt.cpp">
<Filter>audioengine</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\audio\winrt\AudioSourceReader.cpp">
<Filter>audioengine</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3D.cpp">
<Filter>physics3d</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DComponent.cpp">
<Filter>physics3d</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DConstraint.cpp">
<Filter>physics3d</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DDebugDrawer.cpp">
<Filter>physics3d</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DObject.cpp">
<Filter>physics3d</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DShape.cpp">
<Filter>physics3d</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DWorld.cpp">
<Filter>physics3d</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysicsSprite3D.cpp">
<Filter>physics3d</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCUserDefault-winrt.cpp">
<Filter>base</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="2d">
@ -3662,6 +3734,12 @@
<Filter Include="external\poly2tri\sweep">
<UniqueIdentifier>{932c5f6e-07b3-4b34-97ae-2f3d42024149}</UniqueIdentifier>
</Filter>
<Filter Include="audioengine">
<UniqueIdentifier>{bd1a6214-d6e0-4341-a1fc-79da99b55e35}</UniqueIdentifier>
</Filter>
<Filter Include="physics3d">
<UniqueIdentifier>{e6f8ab69-f66f-48be-a40f-e33c08e77516}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)..\..\..\cocos2d.def" />
@ -3777,4 +3855,9 @@
<Filter>3d</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Text Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CMakeLists.txt">
<Filter>physics3d</Filter>
</Text>
</ItemGroup>
</Project>

View File

@ -30,6 +30,9 @@
<ProjectReference Include="..\..\..\..\..\external\Box2D\proj.win8.1-universal\libbox2d.Windows\libbox2d.Windows.vcxproj">
<Project>{3b26a12d-3a44-47ea-82d2-282660fc844d}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\external\bullet\proj.win8.1-universal\libbullet.Windows\libbullet.Windows.vcxproj">
<Project>{ec2b1292-2d8c-4feb-a84b-2550b32c1ae7}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\editor-support\spine\proj.win8.1-universal\libSpine.Windows\libSpine.Windows.vcxproj">
<Project>{f3550fe0-c795-44f6-8feb-093eb68143ae}</Project>
</ProjectReference>
@ -157,7 +160,7 @@
<AdditionalOptions>/Zm384 /bigobj %(AdditionalOptions)</AdditionalOptions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\zlib\include;$(EngineRoot)external\freetype2\include\winrt_8.1\freetype2;$(EngineRoot)external\websockets\include\winrt_8.1;$(EngineRoot)external\curl\include\winrt_8.1;$(EngineRoot)external\tiff\include\winrt_8.1;$(EngineRoot)external\jpeg\include\winrt_8.1;$(EngineRoot)external\png\include\winrt_8.1;$(EngineRoot)external\protobuf-lite\src;$(EngineRoot)external\protobuf-lite\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_DEBUG;COCOS2D_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;CC_ENABLE_BULLET_INTEGRATION=1;_DEBUG;COCOS2D_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
@ -177,7 +180,7 @@
<AdditionalOptions>/Zm384 /bigobj %(AdditionalOptions)</AdditionalOptions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\zlib\include;$(EngineRoot)external\freetype2\include\winrt_8.1\freetype2;$(EngineRoot)external\websockets\include\winrt_8.1;$(EngineRoot)external\curl\include\winrt_8.1;$(EngineRoot)external\tiff\include\winrt_8.1;$(EngineRoot)external\jpeg\include\winrt_8.1;$(EngineRoot)external\png\include\winrt_8.1;$(EngineRoot)external\protobuf-lite\src;$(EngineRoot)external\protobuf-lite\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;CC_ENABLE_BULLET_INTEGRATION=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
@ -197,7 +200,7 @@
<AdditionalOptions>/Zm384 /bigobj %(AdditionalOptions)</AdditionalOptions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\zlib\include;$(EngineRoot)external\freetype2\include\winrt_8.1\freetype2;$(EngineRoot)external\websockets\include\winrt_8.1;$(EngineRoot)external\curl\include\winrt_8.1;$(EngineRoot)external\tiff\include\winrt_8.1;$(EngineRoot)external\jpeg\include\winrt_8.1;$(EngineRoot)external\png\include\winrt_8.1;$(EngineRoot)external\protobuf-lite\src;$(EngineRoot)external\protobuf-lite\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_DEBUG;COCOS2D_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;CC_ENABLE_BULLET_INTEGRATION=1;_DEBUG;COCOS2D_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
@ -217,7 +220,7 @@
<AdditionalOptions>/Zm384 /bigobj %(AdditionalOptions)</AdditionalOptions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\zlib\include;$(EngineRoot)external\freetype2\include\winrt_8.1\freetype2;$(EngineRoot)external\websockets\include\winrt_8.1;$(EngineRoot)external\curl\include\winrt_8.1;$(EngineRoot)external\tiff\include\winrt_8.1;$(EngineRoot)external\jpeg\include\winrt_8.1;$(EngineRoot)external\png\include\winrt_8.1;$(EngineRoot)external\protobuf-lite\src;$(EngineRoot)external\protobuf-lite\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;CC_ENABLE_BULLET_INTEGRATION=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
@ -237,7 +240,7 @@
<AdditionalOptions>/Zm384 /bigobj %(AdditionalOptions)</AdditionalOptions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\zlib\include;$(EngineRoot)external\freetype2\include\winrt_8.1\freetype2;$(EngineRoot)external\websockets\include\winrt_8.1;$(EngineRoot)external\curl\include\winrt_8.1;$(EngineRoot)external\tiff\include\winrt_8.1;$(EngineRoot)external\jpeg\include\winrt_8.1;$(EngineRoot)external\png\include\winrt_8.1;$(EngineRoot)external\protobuf-lite\src;$(EngineRoot)external\protobuf-lite\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_DEBUG;COCOS2D_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;CC_ENABLE_BULLET_INTEGRATION=1;_DEBUG;COCOS2D_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
@ -257,7 +260,7 @@
<AdditionalOptions>/Zm384 /bigobj %(AdditionalOptions)</AdditionalOptions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\zlib\include;$(EngineRoot)external\freetype2\include\winrt_8.1\freetype2;$(EngineRoot)external\websockets\include\winrt_8.1;$(EngineRoot)external\curl\include\winrt_8.1;$(EngineRoot)external\tiff\include\winrt_8.1;$(EngineRoot)external\jpeg\include\winrt_8.1;$(EngineRoot)external\png\include\winrt_8.1;$(EngineRoot)external\protobuf-lite\src;$(EngineRoot)external\protobuf-lite\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;CC_ENABLE_BULLET_INTEGRATION=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>

View File

@ -22,6 +22,9 @@
<ProjectReference Include="..\..\..\..\..\external\Box2D\proj.win8.1-universal\libbox2d.WindowsPhone\libbox2d.WindowsPhone.vcxproj">
<Project>{22f798d8-bfff-4754-996f-a5395343d5ec}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\external\bullet\proj.win8.1-universal\libbullet.WindowsPhone\libbullet.WindowsPhone.vcxproj">
<Project>{e35634bd-b91b-4a6d-b957-96f56dd065f9}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\editor-support\spine\proj.win8.1-universal\libSpine.WindowsPhone\libSpine.WindowsPhone.vcxproj">
<Project>{cc1da216-a80d-4be4-b309-acb6af313aff}</Project>
</ProjectReference>
@ -111,7 +114,7 @@
<AdditionalOptions>/Zm384 /bigobj %(AdditionalOptions)</AdditionalOptions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>$(EngineRoot)external\wp_8.1-specific\zlib\include;$(EngineRoot)external\freetype2\include\wp_8.1\freetype2;$(EngineRoot)external\websockets\include\wp_8.1;$(EngineRoot)external\curl\include\wp_8.1;$(EngineRoot)external\tiff\include\wp_8.1;$(EngineRoot)external\jpeg\include\wp_8.1;$(EngineRoot)external\png\include\wp_8.1;$(EngineRoot)external\protobuf-lite\src;$(EngineRoot)external\protobuf-lite\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>CC_WINDOWS_PHONE_8_1;_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_DEBUG;COCOS2D_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>CC_WINDOWS_PHONE_8_1;_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;CC_ENABLE_BULLET_INTEGRATION=1;_DEBUG;COCOS2D_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
@ -131,7 +134,7 @@
<AdditionalOptions>/Zm384 /bigobj %(AdditionalOptions)</AdditionalOptions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>$(EngineRoot)external\wp_8.1-specific\zlib\include;$(EngineRoot)external\freetype2\include\wp_8.1\freetype2;$(EngineRoot)external\websockets\include\wp_8.1;$(EngineRoot)external\curl\include\wp_8.1;$(EngineRoot)external\tiff\include\wp_8.1;$(EngineRoot)external\jpeg\include\wp_8.1;$(EngineRoot)external\png\include\wp_8.1;$(EngineRoot)external\protobuf-lite\src;$(EngineRoot)external\protobuf-lite\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>CC_WINDOWS_PHONE_8_1;_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>CC_WINDOWS_PHONE_8_1;_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;CC_ENABLE_BULLET_INTEGRATION=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
@ -151,7 +154,7 @@
<AdditionalOptions>/Zm384 /bigobj %(AdditionalOptions)</AdditionalOptions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>$(EngineRoot)external\wp_8.1-specific\zlib\include;$(EngineRoot)external\freetype2\include\wp_8.1\freetype2;$(EngineRoot)external\websockets\include\wp_8.1;$(EngineRoot)external\curl\include\wp_8.1;$(EngineRoot)external\tiff\include\wp_8.1;$(EngineRoot)external\jpeg\include\wp_8.1;$(EngineRoot)external\png\include\wp_8.1;$(EngineRoot)external\protobuf-lite\src;$(EngineRoot)external\protobuf-lite\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>CC_WINDOWS_PHONE_8_1;_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_DEBUG;COCOS2D_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>CC_WINDOWS_PHONE_8_1;_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;CC_ENABLE_BULLET_INTEGRATION=1;_DEBUG;COCOS2D_DEBUG=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
@ -171,7 +174,7 @@
<AdditionalOptions>/Zm384 /bigobj %(AdditionalOptions)</AdditionalOptions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>$(EngineRoot)external\wp_8.1-specific\zlib\include;$(EngineRoot)external\freetype2\include\wp_8.1\freetype2;$(EngineRoot)external\websockets\include\wp_8.1;$(EngineRoot)external\curl\include\wp_8.1;$(EngineRoot)external\tiff\include\wp_8.1;$(EngineRoot)external\jpeg\include\wp_8.1;$(EngineRoot)external\png\include\wp_8.1;$(EngineRoot)external\protobuf-lite\src;$(EngineRoot)external\protobuf-lite\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>CC_WINDOWS_PHONE_8_1;_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>CC_WINDOWS_PHONE_8_1;_USRDLL;_LIB;COCOS2DXWIN32_EXPORTS;_USE3DDLL;_EXPORT_DLL_;_USRSTUDIODLL;_USREXDLL;_USEGUIDLL;CC_ENABLE_CHIPMUNK_INTEGRATION=1;CC_ENABLE_BULLET_INTEGRATION=1;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>

View File

@ -15,7 +15,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<DisableSpecificWarnings>4056;4244;4251;4756;4453;28204;</DisableSpecificWarnings>
<DisableSpecificWarnings>4056;4244;4251;4756;4453;28204;4099;</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>libGLESv2.lib;libEGL.lib;ws2_32.lib;libwebsockets.lib;libcurl.lib;chipmunk.lib;zlib.lib;freetype.lib;sqlite3.lib;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib;dxguid.lib;xaudio2.lib;mfcore.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>

View File

@ -230,10 +230,10 @@ void BillBoard::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
//FIXME: frustum culling here
flags |= Node::FLAGS_RENDER_AS_3D;
_quadCommand.init(0, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, _modelViewTransform, flags);
_quadCommand.setTransparent(true);
_quadCommand.set3D(true);
renderer->addCommand(&_quadCommand);
_trianglesCommand.init(0, _texture->getName(), getGLProgramState(), _blendFunc, getRenderedTriangles(), _modelViewTransform, flags);
_trianglesCommand.setTransparent(true);
_trianglesCommand.set3D(true);
renderer->addCommand(&_trianglesCommand);
}
void BillBoard::setMode( Mode mode )

View File

@ -701,7 +701,7 @@ void Sprite3D::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
#if CC_USE_CULLING
// camera clipping
if(!Camera::getVisitingCamera()->isVisibleInFrustum(&this->getAABB()))
if(Camera::getVisitingCamera() && !Camera::getVisitingCamera()->isVisibleInFrustum(&this->getAABB()))
return;
#endif

View File

@ -33,6 +33,7 @@ USING_NS_CC;
#include "renderer/CCRenderer.h"
#include "renderer/CCGLProgramStateCache.h"
#include "renderer/ccGLStateCache.h"
#include "renderer/CCRenderState.h"
#include "base/CCDirector.h"
#include "2d/CCCamera.h"
@ -79,6 +80,12 @@ bool Terrain::initProperties()
auto state = GLProgramState::create(shader);
setGLProgramState(state);
_stateBlock->setBlend(false);
_stateBlock->setDepthWrite(true);
_stateBlock->setDepthTest(true);
_stateBlock->setCullFace(true);
setDrawWire(false);
setIsEnableFrustumCull(true);
setAnchorPoint(Vec2(0,0));
@ -104,34 +111,16 @@ void Terrain::onDraw(const Mat4 &transform, uint32_t flags)
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
}
#endif
GLboolean blendCheck = glIsEnabled(GL_BLEND);
if(blendCheck)
{
glDisable(GL_BLEND);
}
_stateBlock->bind();
GL::enableVertexAttribs(1<<_positionLocation | 1 << _texcordLocation | 1<<_normalLocation);
glProgram->setUniformsForBuiltins(transform);
GLboolean depthMaskCheck;
glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMaskCheck);
if(!depthMaskCheck)
{
glDepthMask(GL_TRUE);
}
GLboolean CullFaceCheck =glIsEnabled(GL_CULL_FACE);
if(!CullFaceCheck)
{
glEnable(GL_CULL_FACE);
}
GLboolean depthTestCheck;
depthTestCheck = glIsEnabled(GL_DEPTH_TEST);
if(!depthTestCheck)
{
glEnable(GL_DEPTH_TEST);
}
if(!_alphaMap)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,_detailMapTextures[0]->getName());
GL::bindTexture2D(_detailMapTextures[0]->getName());
glUniform1i(_detailMapLocation[0],0);
glUniform1i(_alphaIsHasAlphaMapLocation,0);
}else
@ -139,7 +128,7 @@ void Terrain::onDraw(const Mat4 &transform, uint32_t flags)
for(int i =0;i<_maxDetailMapValue;i++)
{
glActiveTexture(GL_TEXTURE0+i);
glBindTexture(GL_TEXTURE_2D,_detailMapTextures[i]->getName());
GL::bindTexture2D(_detailMapTextures[i]->getName());
glUniform1i(_detailMapLocation[i],i);
glUniform1f(_detailMapSizeLocation[i],_terrainData._detailMaps[i]._detailMapSize);
@ -148,7 +137,7 @@ void Terrain::onDraw(const Mat4 &transform, uint32_t flags)
glUniform1i(_alphaIsHasAlphaMapLocation,1);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D,_alphaMap->getName());
GL::bindTexture2D(_alphaMap->getName());
glUniform1i(_alphaMapLocation,4);
}
@ -180,28 +169,7 @@ void Terrain::onDraw(const Mat4 &transform, uint32_t flags)
_isCameraViewChanged = false;
}
glActiveTexture(GL_TEXTURE0);
if(depthTestCheck)
{
}else
{
glDisable(GL_DEPTH_TEST);
}
if(depthMaskCheck)
{
}else
{
glDepthMask(GL_FALSE);
}
if(CullFaceCheck)
{
}else
{
glEnable(GL_CULL_FACE);
}
if(blendCheck)
{
glEnable(GL_BLEND);
}
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
if(_isDrawWire)//reset state.
{
@ -260,8 +228,12 @@ bool Terrain::initHeightMap(const char * heightMap)
}
Terrain::Terrain()
: _alphaMap(nullptr)
, _stateBlock(nullptr)
{
_alphaMap = nullptr;
_stateBlock = RenderState::StateBlock::create();
CC_SAFE_RETAIN(_stateBlock);
_customCommand.setTransparent(false);
_customCommand.set3D(true);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
@ -453,6 +425,8 @@ void Terrain::setIsEnableFrustumCull(bool bool_value)
Terrain::~Terrain()
{
CC_SAFE_RELEASE(_stateBlock);
_alphaMap->release();
_heightMapImage->release();
delete _quadRoot;
@ -832,7 +806,6 @@ void Terrain::reload()
}
}
CCLOG("recreate");
initTextures();
_chunkLodIndicesSet.clear();
_chunkLodIndicesSkirtSet.clear();

View File

@ -24,15 +24,18 @@ THE SOFTWARE.
#ifndef CC_TERRAIN_H
#define CC_TERRAIN_H
#include <vector>
#include "2d/CCNode.h"
#include "2d/CCCamera.h"
#include "renderer/CCTexture2D.h"
#include "renderer/CCCustomCommand.h"
#include "renderer/CCRenderState.h"
#include "3d/CCAABB.h"
#include "3d/CCRay.h"
#include <vector>
#include "base/CCEventListenerCustom.h"
#include "base/CCEventDispatcher.h"
NS_CC_BEGIN
/**
@ -81,7 +84,7 @@ NS_CC_BEGIN
* We can use ray-terrain intersection to pick a point of the terrain;
* Also we can get an arbitrary point of the terrain's height and normal vector for convenience .
**/
class CC_DLL Terrain :public Node
class CC_DLL Terrain : public Node
{
public:
@ -433,6 +436,7 @@ protected:
ChunkIndices insertIndicesLOD(int neighborLod[4], int selfLod, GLushort * indices, int size);
ChunkIndices insertIndicesLODSkirt(int selfLod, GLushort * indices, int size);
protected:
std::vector <ChunkLODIndices> _chunkLodIndicesSet;
std::vector<ChunkLODIndicesSkirt> _chunkLodIndicesSkirtSet;
@ -469,6 +473,9 @@ protected:
GLint _alphaMapLocation;
GLint _alphaIsHasAlphaMapLocation;
GLint _detailMapSizeLocation[4];
RenderState::StateBlock* _stateBlock;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
EventListenerCustom* _backToForegroundListener;
#endif

View File

@ -103,6 +103,7 @@ math/TransformUtils.cpp \
math/Vec2.cpp \
math/Vec3.cpp \
math/Vec4.cpp \
base/CCNinePatchImageParser.cpp \
base/CCAsyncTaskPool.cpp \
base/CCAutoreleasePool.cpp \
base/CCConfiguration.cpp \

View File

@ -24,7 +24,7 @@
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
#if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
#include "audio/include/AudioEngine.h"
#include "platform/CCFileUtils.h"
@ -36,6 +36,8 @@
#include "apple/AudioEngine-inl.h"
#elif CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
#include "win32/AudioEngine-win32.h"
#elif CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
#include "winrt/AudioEngine-winrt.h"
#endif
#define TIME_DELAY_PRECISION 0.0001

View File

@ -23,7 +23,7 @@
****************************************************************************/
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
#if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
#ifndef __AUDIO_ENGINE_H_
#define __AUDIO_ENGINE_H_

View File

@ -38,7 +38,7 @@
#endif
#include "CCPlatformMacros.h"
#define QUEUEBUFFER_NUM 3
#define QUEUEBUFFER_NUM 5
#define QUEUEBUFFER_TIME_STEP 0.1f
NS_CC_BEGIN

View File

@ -62,6 +62,7 @@ namespace cocos2d {
for (int index = 0; index < _numThread; ++index) {
_tasks.push_back(nullptr);
_threads.push_back( std::thread( std::bind(&AudioEngineThreadPool::threadFunc,this,index) ) );
_threads[index].detach();
}
}
@ -78,7 +79,7 @@ namespace cocos2d {
if (targetIndex == -1) {
_tasks.push_back(task);
_threads.push_back( std::thread( std::bind(&AudioEngineThreadPool::threadFunc,this,_numThread) ) );
_threads[_numThread].detach();
_numThread++;
}
_taskMutex.unlock();
@ -212,16 +213,14 @@ int AudioEngineImpl::play2d(const std::string &filePath ,bool loop ,float volume
auto it = _audioCaches.find(filePath);
if (it == _audioCaches.end()) {
audioCache = &_audioCaches[filePath];
auto ext = filePath.substr(filePath.rfind('.'));
transform(ext.begin(), ext.end(), ext.begin(), tolower);
auto ext = strchr(filePath.c_str(), '.');
bool eraseCache = true;
if (ext.compare(".ogg") == 0){
if (_stricmp(ext, ".ogg") == 0){
audioCache->_fileFormat = AudioCache::FileFormat::OGG;
eraseCache = false;
}
else if (ext.compare(".mp3") == 0){
else if (_stricmp(ext, ".mp3") == 0){
audioCache->_fileFormat = AudioCache::FileFormat::MP3;
if (MPG123_LAZYINIT){
@ -239,7 +238,7 @@ int AudioEngineImpl::play2d(const std::string &filePath ,bool loop ,float volume
}
}
else{
log("unsupported media type:%s\n",ext.c_str());
log("unsupported media type:%s\n", ext);
}
if (eraseCache){
@ -380,7 +379,14 @@ bool AudioEngineImpl::stop(int audioID)
alSourcei(player._alSource, AL_BUFFER, NULL);
_alSourceUsed[player._alSource] = false;
if (player._streamingSource)
{
player.notifyExitThread();
}
else
{
_audioPlayers.erase(audioID);
}
return ret;
}
@ -394,7 +400,19 @@ void AudioEngineImpl::stopAll()
_alSourceUsed[_alSources[index]] = false;
}
_audioPlayers.clear();
for (auto it = _audioPlayers.begin(); it != _audioPlayers.end();)
{
auto& player = it->second;
if (player._streamingSource)
{
player.notifyExitThread();
++it;
}
else
{
it = _audioPlayers.erase(it);
}
}
}
float AudioEngineImpl::getDuration(int audioID)
@ -498,7 +516,11 @@ void AudioEngineImpl::update(float dt)
auto& player = it->second;
alGetSourcei(player._alSource, AL_SOURCE_STATE, &sourceState);
if (player._ready && sourceState == AL_STOPPED) {
if (player._readForRemove)
{
it = _audioPlayers.erase(it);
}
else if (player._ready && sourceState == AL_STOPPED) {
_alSourceUsed[player._alSource] = false;
if (player._finishCallbak) {
auto& audioInfo = AudioEngine::_audioIDInfoMap[audioID];
@ -507,8 +529,16 @@ void AudioEngineImpl::update(float dt)
AudioEngine::remove(audioID);
if (player._streamingSource)
{
player.notifyExitThread();
++it;
}
else
{
it = _audioPlayers.erase(it);
}
}
else{
++it;
}

View File

@ -42,6 +42,7 @@ AudioPlayer::AudioPlayer()
, _finishCallbak(nullptr)
, _ready(false)
, _audioCache(nullptr)
, _readForRemove(false)
{
}
@ -59,13 +60,17 @@ AudioPlayer::AudioPlayer(const AudioPlayer& player)
AudioPlayer::~AudioPlayer()
{
_exitThread = true;
if (_audioCache && _audioCache->_queBufferFrames > 0) {
_sleepCondition.notify_all();
if (_rotateBufferThread.joinable()) {
_rotateBufferThread.join();
alDeleteBuffers(QUEUEBUFFER_NUM, _bufferIds);
}
alDeleteBuffers(3, _bufferIds);
}
void AudioPlayer::notifyExitThread()
{
if (_audioCache && _audioCache->_queBufferFrames > 0) {
std::unique_lock<std::mutex> lk(_sleepMutex);
_exitThread = true;
_sleepCondition.notify_all();
}
}
@ -94,11 +99,9 @@ bool AudioPlayer::play2d(AudioCache* cache)
alSourcei(_alSource, AL_LOOPING, AL_FALSE);
auto alError = alGetError();
alGenBuffers(3, _bufferIds);
alGenBuffers(QUEUEBUFFER_NUM, _bufferIds);
alError = alGetError();
if (alError == AL_NO_ERROR) {
_rotateBufferThread = std::thread(&AudioPlayer::rotateBufferThread,this, _audioCache->_queBufferFrames * QUEUEBUFFER_NUM + 1);
for (int index = 0; index < QUEUEBUFFER_NUM; ++index) {
alBufferData(_bufferIds[index], _audioCache->_alBufferFormat, _audioCache->_queBuffers[index], _audioCache->_queBufferSize[index], _audioCache->_sampleRate);
}
@ -110,15 +113,24 @@ bool AudioPlayer::play2d(AudioCache* cache)
}
}
if (_streamingSource)
{
_rotateBufferThread = std::thread(&AudioPlayer::rotateBufferThread, this, _audioCache->_queBufferFrames * QUEUEBUFFER_NUM + 1);
_rotateBufferThread.detach();
}
else
{
alSourcePlay(_alSource);
_ready = true;
auto alError = alGetError();
auto alError = alGetError();
if (alError != AL_NO_ERROR) {
log("%s:alSourcePlay error code:%x\n", __FUNCTION__,alError);
log("%s:alSourcePlay error code:%x\n", __FUNCTION__, alError);
return false;
}
_ready = true;
}
return true;
}
@ -177,9 +189,13 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
break;
}
alSourcePlay(_alSource);
while (!_exitThread) {
alGetSourcei(_alSource, AL_SOURCE_STATE, &sourceState);
if (sourceState == AL_PLAYING) {
_ready = true;
alGetSourcei(_alSource, AL_BUFFERS_PROCESSED, &bufferProcessed);
while (bufferProcessed > 0) {
bufferProcessed--;
@ -250,11 +266,13 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
}
}
if (_exitThread){
std::unique_lock<std::mutex> lk(_sleepMutex);
if (_exitThread)
{
break;
}
std::unique_lock<std::mutex> lk(_sleepMutex);
_sleepCondition.wait_for(lk,std::chrono::milliseconds(75));
_sleepCondition.wait_for(lk,std::chrono::milliseconds(35));
}
ExitBufferThread:
switch (audioFileFormat)
@ -272,6 +290,7 @@ ExitBufferThread:
break;
}
free(tmpBuffer);
_readForRemove = true;
}
bool AudioPlayer::setLoop(bool loop)

View File

@ -37,6 +37,7 @@
#include <AL/al.h>
#endif
#include "CCPlatformMacros.h"
#include "AudioCache.h"
NS_CC_BEGIN
namespace experimental{
@ -55,6 +56,7 @@ public:
bool setTime(float time);
float getTime() { return _currTime;}
bool setLoop(bool loop);
void notifyExitThread();
protected:
void rotateBufferThread(int offsetFrame);
@ -73,11 +75,12 @@ protected:
float _currTime;
bool _timeDirty;
bool _streamingSource;
ALuint _bufferIds[3];
ALuint _bufferIds[QUEUEBUFFER_NUM];
std::thread _rotateBufferThread;
std::mutex _sleepMutex;
std::condition_variable _sleepCondition;
bool _exitThread;
bool _readForRemove;
friend class AudioEngineImpl;
};

View File

@ -0,0 +1,568 @@
/*
* cocos2d-x http://www.cocos2d-x.org
*
* Copyright (c) 2010-2011 - cocos2d-x community
*
* Portions Copyright (c) Microsoft Open Technologies, Inc.
* All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
#include "AudioCachePlayer.h"
using namespace cocos2d;
using namespace cocos2d::experimental;
inline void ThrowIfFailed(HRESULT hr)
{
if (FAILED(hr)) {
// Set a breakpoint on this line to catch XAudio2 API errors.
throw Platform::Exception::CreateException(hr);
}
}
// AudioCache
AudioCache::AudioCache()
: _isReady(false)
, _fileFullPath("")
, _srcReader(nullptr)
, _fileFormat(FileFormat::UNKNOWN)
{
_callbacks.clear();
memset(&_audInfo, 0, sizeof(AudioInfo));
}
AudioCache::AudioCache(const AudioCache& obj)
{
// TODO
}
AudioCache& AudioCache::operator=(const AudioCache& rhs)
{
// TODO
return *this;
}
AudioCache::~AudioCache()
{
_callbacks.clear();
if (nullptr != _srcReader) {
delete _srcReader;
_srcReader = nullptr;
}
}
void AudioCache::readDataTask()
{
std::wstring path(_fileFullPath.begin(), _fileFullPath.end());
if (nullptr != _srcReader) {
delete _srcReader;
_srcReader = nullptr;
}
switch (_fileFormat)
{
case FileFormat::WAV:
_srcReader = new (std::nothrow) WAVReader();
if (_srcReader->initialize(_fileFullPath)) {
_audInfo._totalAudioBytes = _srcReader->getTotalAudioBytes();
_audInfo._wfx = _srcReader->getWaveFormatInfo();
_isReady = true;
invokeCallbacks();
}
break;
case FileFormat::OGG:
break;
case FileFormat::MP3:
break;
case FileFormat::UNKNOWN:
default:
break;
}
}
void AudioCache::addCallback(const std::function<void()> &callback)
{
_cbMutex.lock();
if (_isReady) {
callback();
}
else {
_callbacks.push_back(callback);
}
_cbMutex.unlock();
}
void AudioCache::invokeCallbacks()
{
_cbMutex.lock();
auto cnt = _callbacks.size();
for (size_t ind = 0; ind < cnt; ind++)
{
_callbacks[ind]();
}
_callbacks.clear();
_cbMutex.unlock();
}
bool AudioCache::getChunk(AudioDataChunk& chunk)
{
bool ret = false;
if (nullptr != _srcReader) {
ret = _srcReader->consumeChunk(chunk);
}
return ret;
}
void AudioCache::doBuffering()
{
if (isStreamingSource()){
_srcReader->produceChunk();
}
}
bool AudioCache::isStreamingSource()
{
if (nullptr != _srcReader) {
return _srcReader->isStreamingSource();
}
return false;
}
void AudioCache::seek(const float ratio)
{
if (nullptr != _srcReader){
_srcReader->seekTo(ratio);
}
}
// AudioPlayer
AudioPlayer::AudioPlayer()
: _loop(false)
, _ready(false)
, _current(0.0)
, _volume(0.0)
, _duration(0.0)
, _cache(nullptr)
, _totalSamples(0)
, _samplesOffset(0)
, _criticalError(false)
, _isStreaming(false)
, _finishCallback(nullptr)
, _xaMasterVoice(nullptr)
, _xaSourceVoice(nullptr)
, _state(AudioPlayerState::INITIALZING)
{
init();
}
AudioPlayer::~AudioPlayer()
{
free();
}
void AudioPlayer::stop()
{
_stop();
}
void AudioPlayer::pause()
{
_stop(true);
}
bool AudioPlayer::update()
{
if (_criticalError){
free();
init();
}
if (_cache != nullptr) {
_cache->doBuffering();
}
//log("bufferQueued: %d, _current: %f", _cachedBufferQ.size(), _current);
return _criticalError;
}
void AudioPlayer::resume()
{
_play(true);
}
bool AudioPlayer::isInError()
{
return _criticalError;
}
float AudioPlayer::getDuration()
{
if (nullptr == _cache) {
return _duration;
}
auto fmt = _cache->_audInfo._wfx;
if (!fmt.nChannels) {
return _duration;
}
if ((int)_duration <= 0)
{
switch (fmt.wFormatTag)
{
case WAVE_FORMAT_PCM:
case WAVE_FORMAT_ADPCM:
_duration = (float(_cache->_audInfo._totalAudioBytes / ((fmt.wBitsPerSample / 8) * fmt.nChannels)) / fmt.nSamplesPerSec) * 1000;
_totalSamples = fmt.nSamplesPerSec * _duration / 1000;
break;
default:
break;
}
}
return _duration;
}
float AudioPlayer::getCurrentTime()
{
_stMutex.lock();
auto samplesPlayed = getSourceVoiceState().SamplesPlayed;
//log("_samplesOffset: %lu, samplesPlayed: %lu, _current: %f", (UINT32)_samplesOffset, (UINT32)samplesPlayed, _current);
_current += ((samplesPlayed - _samplesOffset) / (float)_totalSamples) * _duration;
_current = _current > _duration ? 0.0 : _current;
_samplesOffset = samplesPlayed;
_stMutex.unlock();
return _current;
}
bool AudioPlayer::setTime(float time)
{
bool ret = true;
_stop();
if (!_isStreaming) {
auto fmt = _cache->_audInfo._wfx;
int seek = (time / _duration) * _totalSamples;
seek -= (seek % (fmt.nChannels * fmt.nBlockAlign));
_xaBuffer.LoopCount = 0;
_xaBuffer.PlayBegin = seek;
_xaBuffer.PlayLength = _totalSamples - seek;
if (_xaBuffer.PlayBegin >= _totalSamples) {
_xaBuffer.PlayBegin = _totalSamples - (fmt.nChannels * fmt.nBlockAlign);
_xaBuffer.PlayLength = (fmt.nChannels * fmt.nBlockAlign);
}
}
_stMutex.lock();
_samplesOffset = getSourceVoiceState().SamplesPlayed;
_current = time;
_stMutex.unlock();
_play();
return ret;
}
void AudioPlayer::setVolume(float volume)
{
if (_xaMasterVoice != nullptr){
if (FAILED(_xaMasterVoice->SetVolume(volume))) {
error();
}
}
}
bool AudioPlayer::play2d(AudioCache* cache)
{
bool ret = false;
if (cache != nullptr)
{
_cache = cache;
if (nullptr == _xaSourceVoice && _ready) {
XAUDIO2_SEND_DESCRIPTOR descriptors[1];
descriptors[0].pOutputVoice = _xaMasterVoice;
descriptors[0].Flags = 0;
XAUDIO2_VOICE_SENDS sends = { 0 };
sends.SendCount = 1;
sends.pSends = descriptors;
ThrowIfFailed(_xaEngine->CreateSourceVoice(&_xaSourceVoice, &cache->_audInfo._wfx, 0, 1.0, this, &sends));
}
_isStreaming = _cache->isStreamingSource();
_duration = getDuration();
ret = _play();
}
return ret;
}
void AudioPlayer::init()
{
memset(&_xaBuffer, 0, sizeof(_xaBuffer));
ThrowIfFailed(XAudio2Create(_xaEngine.ReleaseAndGetAddressOf()));
#if defined(_DEBUG)
XAUDIO2_DEBUG_CONFIGURATION debugConfig = { 0 };
debugConfig.BreakMask = XAUDIO2_LOG_ERRORS;
debugConfig.TraceMask = XAUDIO2_LOG_ERRORS;
_xaEngine->SetDebugConfiguration(&debugConfig);
#endif
_xaEngine->RegisterForCallbacks(this);
ThrowIfFailed(_xaEngine->CreateMasteringVoice(&_xaMasterVoice, XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_SAMPLERATE, 0, nullptr, nullptr, AudioCategory_GameMedia));
_ready = true;
_state = AudioPlayerState::READY;
}
void AudioPlayer::free()
{
_stop();
memset(&_xaBuffer, 0, sizeof(_xaBuffer));
if (_xaEngine) {
_xaEngine->StopEngine();
}
if (_xaSourceVoice != nullptr) {
_xaSourceVoice->DestroyVoice();
_xaSourceVoice = nullptr;
}
if (_xaMasterVoice != nullptr) {
_xaMasterVoice->DestroyVoice();
_xaMasterVoice = nullptr;
}
while (!_cachedBufferQ.empty()) {
popBuffer();
}
}
bool AudioPlayer::_play(bool resume)
{
do {
if (!resume) {
_cache->seek(_current / _duration);
submitBuffers();
}
if (_state == AudioPlayerState::PAUSED && !resume || nullptr == _xaSourceVoice) break;
if (FAILED(_xaSourceVoice->Start())) {
error();
}
else {
_state = AudioPlayerState::PLAYING;
}
} while (false);
return !_criticalError;
}
void AudioPlayer::_stop(bool pause)
{
if (_xaSourceVoice != nullptr) {
if (FAILED(_xaSourceVoice->Stop())) {
error();
}
else {
if (!pause) {
_xaSourceVoice->FlushSourceBuffers();
if (_state != AudioPlayerState::PAUSED) _state = AudioPlayerState::STOPPED;
}
else {
_state = AudioPlayerState::PAUSED;
}
}
}
}
void AudioPlayer::error()
{
_criticalError = true;
_ready = false;
_state = AudioPlayerState::ERRORED;
}
void AudioPlayer::popBuffer()
{
_bqMutex.lock();
if (!_cachedBufferQ.empty()) {
delete[] _cachedBufferQ.front()._data;
_cachedBufferQ.pop();
}
_bqMutex.unlock();
}
bool AudioPlayer::submitBuffers()
{
bool ret = false;
_bqMutex.lock();
do {
if (nullptr == _xaSourceVoice) break;
if (!_cachedBufferQ.size() || (_isStreaming && _cachedBufferQ.size() < QUEUEBUFFER_NUM)) {
AudioDataChunk chunk;
if (_cache->getChunk(chunk)) {
_xaBuffer.AudioBytes = chunk._dataSize;
_xaBuffer.pAudioData = chunk._data;
_xaBuffer.Flags = chunk._endOfStream ? XAUDIO2_END_OF_STREAM : 0;
_cachedBufferQ.push(chunk);
ret = SUCCEEDED(_xaSourceVoice->SubmitSourceBuffer(&_xaBuffer));
if (!_isStreaming) break;
}
else {
break;
}
}
else if (!_isStreaming) {
ret = SUCCEEDED(_xaSourceVoice->SubmitSourceBuffer(&_xaBuffer));
break;
}
else {
break;
}
} while (ret);
_bqMutex.unlock();
return ret;
}
void AudioPlayer::updateState()
{
if (!_isStreaming) {
_stMutex.lock();
_samplesOffset = getSourceVoiceState().SamplesPlayed;
_stMutex.unlock();
}
else {
if (_cachedBufferQ.size() > getSourceVoiceState(true).BuffersQueued) {
popBuffer();
}
}
}
void AudioPlayer::onBufferRunOut()
{
_stMutex.lock();
_samplesOffset = 0;
_current = 0.0;
_xaBuffer.PlayBegin = _xaBuffer.PlayLength = 0;
_stMutex.unlock();
if (!_loop) {
_stop();
//invokeFinishCallback();
}
else {
_play();
}
}
void AudioPlayer::invokeFinishCallback()
{
if (_finishCallback) {
_finishCallback(0, "");
}
}
XAUDIO2_VOICE_STATE AudioPlayer::getSourceVoiceState(bool fast)
{
XAUDIO2_VOICE_STATE state;
memset(&state, 0, sizeof(XAUDIO2_VOICE_STATE));
if (_xaSourceVoice != nullptr) {
_xaSourceVoice->GetState(&state, fast ? XAUDIO2_VOICE_NOSAMPLESPLAYED : 0);
}
return state;
}
// IXAudio2EngineCallback
void AudioPlayer::OnProcessingPassStart()
{
}
void AudioPlayer::OnProcessingPassEnd()
{
}
void AudioPlayer::OnCriticalError(HRESULT err)
{
UNREFERENCED_PARAMETER(err);
error();
}
// IXAudio2VoiceCallback
void AudioPlayer::OnVoiceProcessingPassStart(UINT32 uBytesRequired)
{
if (uBytesRequired && _isStreaming){
submitBuffers();
}
}
void AudioPlayer::OnVoiceProcessingPassEnd()
{
}
void AudioPlayer::OnStreamEnd()
{
onBufferRunOut();
}
void AudioPlayer::OnBufferStart(void* pBufferContext)
{
UNREFERENCED_PARAMETER(pBufferContext);
}
void AudioPlayer::OnBufferEnd(void* pBufferContext)
{
UNREFERENCED_PARAMETER(pBufferContext);
updateState();
}
void AudioPlayer::OnLoopEnd(void* pBufferContext)
{
UNREFERENCED_PARAMETER(pBufferContext);
if (!_loop) {
_stop();
}
}
void AudioPlayer::OnVoiceError(void* pBufferContext, HRESULT err)
{
UNREFERENCED_PARAMETER(pBufferContext);
UNREFERENCED_PARAMETER(err);
error();
}
#endif

View File

@ -0,0 +1,159 @@
/*
* cocos2d-x http://www.cocos2d-x.org
*
* Copyright (c) 2010-2011 - cocos2d-x community
*
* Portions Copyright (c) Microsoft Open Technologies, Inc.
* All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
#ifndef __AUDIO_CACHE_PLAYER_H_
#define __AUDIO_CACHE_PLAYER_H_
#include "AudioSourceReader.h"
NS_CC_BEGIN
namespace experimental{
typedef struct AudioInfo
{
size_t _totalAudioBytes;
WAVEFORMATEX _wfx;
} AudioInfo;
enum class AudioPlayerState
{
ERRORED = -1,
INITIALZING,
READY,
PLAYING,
PAUSED,
STOPPED
};
class AudioCache
{
public:
AudioCache();
~AudioCache();
void readDataTask();
void addCallback(const std::function<void()> &callback);
bool getChunk(AudioDataChunk& chunk);
void doBuffering();
bool isStreamingSource();
void seek(const float ratio);
protected:
AudioCache(const AudioCache&);
AudioCache& operator=(const AudioCache&);
void invokeCallbacks();
private:
bool _isReady;
AudioInfo _audInfo;
std::mutex _cbMutex;
FileFormat _fileFormat;
std::string _fileFullPath;
AudioSourceReader *_srcReader;
std::vector<std::function<void()>> _callbacks;
friend class AudioPlayer;
friend class AudioEngineImpl;
};
class AudioPlayer : public IXAudio2EngineCallback, IXAudio2VoiceCallback
{
public:
AudioPlayer();
virtual ~AudioPlayer();
void stop();
void pause();
bool update();
void resume();
bool isInError();
float getDuration();
float getCurrentTime();
bool setTime(float time);
void setVolume(float volume);
bool play2d(AudioCache* cache);
AudioPlayerState getState() { return _state; }
protected:
AudioPlayer(AudioPlayer&);
AudioPlayer& operator=(AudioPlayer&);
void init();
void free();
void error();
void popBuffer();
void updateState();
bool submitBuffers();
void onBufferRunOut();
void invokeFinishCallback();
void _stop(bool pause = false);
bool _play(bool resume = false);
XAUDIO2_VOICE_STATE getSourceVoiceState(bool fast = false);
// IXAudio2EngineCallback
STDMETHOD_(void, OnProcessingPassStart) () override;
STDMETHOD_(void, OnProcessingPassEnd) () override;
STDMETHOD_(void, OnCriticalError) (HRESULT error) override;
// IXAudio2VoiceCallback
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32 uBytesRequired) override;
STDMETHOD_(void, OnVoiceProcessingPassEnd) () override;
STDMETHOD_(void, OnStreamEnd) () override;
STDMETHOD_(void, OnBufferStart) (void* pBufferContext) override;
STDMETHOD_(void, OnBufferEnd) (void* pBufferContext) override;
STDMETHOD_(void, OnLoopEnd) (void* pBufferContext) override;
STDMETHOD_(void, OnVoiceError) (void *pBufferContext, HRESULT error) override;
private:
bool _loop;
bool _ready;
float _volume;
float _current;
float _duration;
bool _criticalError;
bool _isStreaming;
UINT64 _totalSamples;
UINT64 _samplesOffset;
XAUDIO2_BUFFER _xaBuffer;
IXAudio2SourceVoice *_xaSourceVoice;
IXAudio2MasteringVoice *_xaMasterVoice;
Microsoft::WRL::ComPtr<IXAudio2> _xaEngine;
AudioCache *_cache;
std::mutex _stMutex;
std::mutex _bqMutex;
AudioPlayerState _state;
std::queue<AudioDataChunk> _cachedBufferQ;
std::function<void(int, const std::string &)> _finishCallback;
friend class AudioEngineImpl;
};
}
NS_CC_END
#endif // __AUDIO_CACHE_PLAYER_H_
#endif

View File

@ -0,0 +1,430 @@
/*
* cocos2d-x http://www.cocos2d-x.org
*
* Copyright (c) 2010-2011 - cocos2d-x community
*
* Portions Copyright (c) Microsoft Open Technologies, Inc.
* All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
#include "AudioEngine-winrt.h"
#include <condition_variable>
using namespace cocos2d;
using namespace cocos2d::experimental;
namespace cocos2d {
namespace experimental {
class AudioEngineThreadPool
{
public:
AudioEngineThreadPool()
: _running(true)
, _numThread(6)
{
_threads.reserve(_numThread);
_tasks.reserve(_numThread);
for (int index = 0; index < _numThread; ++index) {
_tasks.push_back(nullptr);
_threads.push_back(std::thread(std::bind(&AudioEngineThreadPool::threadFunc, this, index)));
}
}
void addTask(const std::function<void()> &task){
_taskMutex.lock();
int targetIndex = -1;
for (int index = 0; index < _numThread; ++index) {
if (_tasks[index] == nullptr) {
targetIndex = index;
_tasks[index] = task;
break;
}
}
if (targetIndex == -1) {
_tasks.push_back(task);
_threads.push_back(std::thread(std::bind(&AudioEngineThreadPool::threadFunc, this, _numThread)));
_numThread++;
}
_taskMutex.unlock();
_sleepCondition.notify_all();
}
void destroy()
{
_running = false;
_sleepCondition.notify_all();
for (int index = 0; index < _numThread; ++index) {
_threads[index].join();
}
}
private:
bool _running;
std::vector<std::thread> _threads;
std::vector< std::function<void()> > _tasks;
void threadFunc(int index)
{
while (_running) {
std::function<void()> task = nullptr;
_taskMutex.lock();
task = _tasks[index];
_taskMutex.unlock();
if (nullptr == task)
{
std::unique_lock<std::mutex> lk(_sleepMutex);
_sleepCondition.wait(lk);
continue;
}
task();
_taskMutex.lock();
_tasks[index] = nullptr;
_taskMutex.unlock();
}
}
int _numThread;
std::mutex _taskMutex;
std::mutex _sleepMutex;
std::condition_variable _sleepCondition;
};
}
}
AudioEngineImpl::AudioEngineImpl()
: _lazyInitLoop(true)
, _currentAudioID(0)
, _threadPool(nullptr)
{
}
AudioEngineImpl::~AudioEngineImpl()
{
_audioCaches.clear();
if (_threadPool) {
_threadPool->destroy();
delete _threadPool;
}
}
bool AudioEngineImpl::init()
{
bool ret = false;
if (nullptr == _threadPool) {
_threadPool = new (std::nothrow) AudioEngineThreadPool();
}
ret = true;
return ret;
}
int AudioEngineImpl::play2d(const std::string &filePath, bool loop, float volume)
{
AudioCache* audioCache = nullptr;
auto it = _audioCaches.find(filePath);
if (it == _audioCaches.end()) {
audioCache = &_audioCaches[filePath];
auto ext = filePath.substr(filePath.rfind('.'));
transform(ext.begin(), ext.end(), ext.begin(), tolower);
bool eraseCache = true;
if (ext.compare(".wav") == 0){
audioCache->_fileFormat = FileFormat::WAV;
eraseCache = false;
}
else if (ext.compare(".ogg") == 0){
audioCache->_fileFormat = FileFormat::OGG;
//eraseCache = false; //TODO add support for OGG
}
else if (ext.compare(".mp3") == 0){
audioCache->_fileFormat = FileFormat::MP3;
//eraseCache = false; //TODO add support for MP3
}
else{
log("unsupported media type:%s\n", ext.c_str());
eraseCache = false;
}
if (eraseCache){
_audioCaches.erase(filePath);
return AudioEngine::INVALID_AUDIO_ID;
}
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filePath);
audioCache->_fileFullPath = fullPath;
_threadPool->addTask(std::bind(&AudioCache::readDataTask, audioCache));
}
else {
audioCache = &it->second;
}
auto player = &_audioPlayers[_currentAudioID];
player->_loop = loop;
player->_volume = volume;
audioCache->addCallback(std::bind(&AudioEngineImpl::_play2d, this, audioCache, _currentAudioID));
if (_lazyInitLoop) {
_lazyInitLoop = false;
auto scheduler = cocos2d::Director::getInstance()->getScheduler();
scheduler->schedule(schedule_selector(AudioEngineImpl::update), this, 0.05f, false);
}
return _currentAudioID++;
}
void AudioEngineImpl::_play2d(AudioCache *cache, int audioID)
{
if (cache->_isReady){
auto playerIt = _audioPlayers.find(audioID);
if (playerIt != _audioPlayers.end()) {
if (playerIt->second.play2d(cache)) {
AudioEngine::_audioIDInfoMap[audioID].state = AudioEngine::AudioState::PLAYING;
}
else{
_threadMutex.lock();
_toRemoveAudioIDs.push_back(audioID);
_threadMutex.unlock();
}
}
}
else {
_threadMutex.lock();
_toRemoveCaches.push_back(cache);
_toRemoveAudioIDs.push_back(audioID);
_threadMutex.unlock();
}
}
void AudioEngineImpl::setVolume(int audioID, float volume)
{
auto& player = _audioPlayers[audioID];
if (player._ready){
player.setVolume(volume);
}
if (player.isInError()) {
log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
}
}
void AudioEngineImpl::setLoop(int audioID, bool loop)
{
auto& player = _audioPlayers[audioID];
if (player._ready) {
player._loop = loop;
}
if (player.isInError()) {
log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
}
}
bool AudioEngineImpl::pause(int audioID)
{
bool ret = false;
auto& player = _audioPlayers[audioID];
if (player._ready) {
player.pause();
AudioEngine::_audioIDInfoMap[audioID].state = AudioEngine::AudioState::PAUSED;
}
ret = !player.isInError();
if (!ret) {
log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
}
return ret;
}
bool AudioEngineImpl::resume(int audioID)
{
bool ret = false;
auto& player = _audioPlayers[audioID];
if (player._ready) {
player.resume();
AudioEngine::_audioIDInfoMap[audioID].state = AudioEngine::AudioState::PLAYING;
}
ret = !player.isInError();
if (!ret) {
log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
}
return ret;
}
bool AudioEngineImpl::stop(int audioID)
{
bool ret = false;
auto& player = _audioPlayers[audioID];
if (player._ready) {
player.stop();
ret = !player.isInError();
}
if (!ret) {
log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
}
_audioPlayers.erase(audioID);
return ret;
}
void AudioEngineImpl::stopAll()
{
for (auto &player : _audioPlayers) {
player.second.stop();
}
_audioPlayers.clear();
}
float AudioEngineImpl::getDuration(int audioID)
{
auto& player = _audioPlayers[audioID];
if (player._ready) {
return player.getDuration();
}
else {
return AudioEngine::TIME_UNKNOWN;
}
}
float AudioEngineImpl::getCurrentTime(int audioID)
{
float ret = 0.0f;
auto& player = _audioPlayers[audioID];
if (player._ready) {
ret = player.getCurrentTime();
}
return ret;
}
bool AudioEngineImpl::setCurrentTime(int audioID, float time)
{
bool ret = false;
auto& player = _audioPlayers[audioID];
if (player._ready) {
ret = player.setTime(time);
}
if (!ret) {
log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
}
return ret;
}
void AudioEngineImpl::setFinishCallback(int audioID, const std::function<void(int, const std::string &)> &callback)
{
_audioPlayers[audioID]._finishCallback = callback;
}
void AudioEngineImpl::update(float dt)
{
int audioID;
if (_threadMutex.try_lock()) {
size_t removeAudioCount = _toRemoveAudioIDs.size();
for (size_t index = 0; index < removeAudioCount; ++index) {
audioID = _toRemoveAudioIDs[index];
auto playerIt = _audioPlayers.find(audioID);
if (playerIt != _audioPlayers.end()) {
if (playerIt->second._finishCallback) {
auto& audioInfo = AudioEngine::_audioIDInfoMap[audioID];
playerIt->second._finishCallback(audioID, *audioInfo.filePath);
}
_audioPlayers.erase(audioID);
AudioEngine::remove(audioID);
}
}
size_t removeCacheCount = _toRemoveCaches.size();
for (size_t index = 0; index < removeCacheCount; ++index) {
auto itEnd = _audioCaches.end();
for (auto it = _audioCaches.begin(); it != itEnd; ++it) {
if (&it->second == _toRemoveCaches[index]) {
_audioCaches.erase(it);
break;
}
}
}
_threadMutex.unlock();
}
for (auto it = _audioPlayers.begin(); it != _audioPlayers.end();) {
audioID = it->first;
auto& player = it->second;
if (player._ready && player._state == AudioPlayerState::STOPPED) {
if (player._finishCallback) {
auto& audioInfo = AudioEngine::_audioIDInfoMap[audioID];
player._finishCallback(audioID, *audioInfo.filePath);
}
AudioEngine::remove(audioID);
it = _audioPlayers.erase(it);
}
else{
player.update();
++it;
}
}
if (_audioPlayers.empty()){
_lazyInitLoop = true;
auto scheduler = cocos2d::Director::getInstance()->getScheduler();
scheduler->unschedule(schedule_selector(AudioEngineImpl::update), this);
}
}
void AudioEngineImpl::uncache(const std::string &filePath)
{
_audioCaches.erase(filePath);
}
void AudioEngineImpl::uncacheAll()
{
_audioCaches.clear();
}
#endif

View File

@ -0,0 +1,82 @@
/*
* cocos2d-x http://www.cocos2d-x.org
*
* Copyright (c) 2010-2011 - cocos2d-x community
*
* Portions Copyright (c) Microsoft Open Technologies, Inc.
* All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
#ifndef __AUDIO_ENGINE_WINRT_H_
#define __AUDIO_ENGINE_WINRT_H_
#define NEAR near
#include <unordered_map>
#include "base/CCRef.h"
#include "AudioEngine.h"
#include "AudioCachePlayer.h"
NS_CC_BEGIN
namespace experimental{
#define MAX_AUDIOINSTANCES 32
class AudioEngineThreadPool;
class CC_DLL AudioEngineImpl : public cocos2d::Ref
{
public:
AudioEngineImpl();
~AudioEngineImpl();
bool init();
int play2d(const std::string &fileFullPath, bool loop, float volume);
void setVolume(int audioID, float volume);
void setLoop(int audioID, bool loop);
bool pause(int audioID);
bool resume(int audioID);
bool stop(int audioID);
void stopAll();
float getDuration(int audioID);
float getCurrentTime(int audioID);
bool setCurrentTime(int audioID, float time);
void setFinishCallback(int audioID, const std::function<void(int, const std::string &)> &callback);
void uncache(const std::string& filePath);
void uncacheAll();
void update(float dt);
private:
void _play2d(AudioCache *cache, int audioID);
private:
std::unordered_map<int, AudioPlayer> _audioPlayers;
std::unordered_map<std::string, AudioCache> _audioCaches;
std::vector<AudioCache*> _toRemoveCaches;
std::mutex _threadMutex;
std::vector<int> _toRemoveAudioIDs;
bool _lazyInitLoop;
int _currentAudioID;
AudioEngineThreadPool* _threadPool;
};
}
NS_CC_END
#endif // __AUDIO_ENGINE_WINRT_H_
#endif

View File

@ -0,0 +1,198 @@
/*
* cocos2d-x http://www.cocos2d-x.org
*
* Copyright (c) 2010-2011 - cocos2d-x community
*
* Portions Copyright (c) Microsoft Open Technologies, Inc.
* All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
#include "AudioSourceReader.h"
using namespace cocos2d;
using namespace cocos2d::experimental;
// AudioFileReader
AudioSourceReader::AudioSourceReader() :
_isStreaming(false)
, _filePath("")
, _audioSize(0)
{
}
AudioSourceReader::~AudioSourceReader()
{
}
// WAVFileReader
WAVReader::WAVReader() :
_bytesRead(0)
, _isDirty(false)
, _streamer(nullptr)
{
}
WAVReader::~WAVReader()
{
flushChunks();
}
bool WAVReader::initialize(const std::string& filePath)
{
bool ret = false;
_isStreaming = false;
_filePath = filePath;
do {
auto fileSize = FileUtils::getInstance()->getFileSize(_filePath);
if (fileSize <= 0)
break;
flushChunks();
_rwMutex.lock();
_streamer = ref new MediaStreamer;
_streamer->Initialize(std::wstring(_filePath.begin(), _filePath.end()).c_str(), true);
_rwMutex.unlock();
_wfx = _streamer->GetOutputWaveFormatEx();
UINT32 dataSize = _streamer->GetMaxStreamLengthInBytes();
if (dataSize <= 0)
break;
_audioSize = dataSize;
if (_audioSize <= PCMDATA_CACHEMAXSIZE) {
produceChunk();
}
else {
_isStreaming = true;
for (int i = 0; i < QUEUEBUFFER_NUM; i++) {
produceChunk();
}
}
ret = true;
} while (false);
return ret;
}
bool WAVReader::consumeChunk(AudioDataChunk& chunk)
{
bool ret = false;
_isDirty = true;
_rwMutex.lock();
if (_chnkQ.size() > 0) {
chunk = _chnkQ.front();
if (_isStreaming) {
_chnkQ.pop();
}
else{
// copy for future requests
auto cpy = new (std::nothrow) unsigned char[chunk._dataSize];
memcpy(cpy, chunk._data, chunk._dataSize);
_chnkQ.front()._data = cpy;
}
ret = true;
}
_rwMutex.unlock();
return ret;
}
void WAVReader::produceChunk()
{
_rwMutex.lock();
int chunkSize = _audioSize;
do {
if (!_isStreaming && _chnkQ.size() || _chnkQ.size() >= QUEUEBUFFER_NUM) {
break;
}
if (_isStreaming) {
chunkSize = std::min(CHUNK_SIZE_MAX, _audioSize - _bytesRead);
}
if (!chunkSize && !_chnkQ.size()) {
auto alignment = _wfx.nChannels * _wfx.nBlockAlign;
_bytesRead -= alignment;
chunkSize = alignment;
}
UINT retSize = 0;
AudioDataChunk chunk = { 0 };
chunk._data = new (std::nothrow) unsigned char[chunkSize];
_streamer->ReadChunk(chunk._data, _bytesRead, chunkSize, &retSize);
if (retSize <= 0) {
delete[] chunk._data;
chunk._data = nullptr;
break;
}
_bytesRead += retSize;
chunk._dataSize = retSize;
chunk._seqNo = ((float)_bytesRead / _audioSize) * ((float)_audioSize / CHUNK_SIZE_MAX);
chunk._endOfStream = (_bytesRead >= _audioSize);
_chnkQ.push(chunk);
} while (false);
_rwMutex.unlock();
}
void WAVReader::seekTo(const float ratio)
{
if (_isStreaming) {
_bytesRead = ratio * _audioSize;
if (!_bytesRead && !_isDirty && _chnkQ.size()) // already in 0.0 position
return;
flushChunks();
switch (_wfx.wFormatTag)
{
case WAVE_FORMAT_PCM:
case WAVE_FORMAT_ADPCM: {
auto alignment = _wfx.nChannels * _wfx.nBlockAlign;
_bytesRead = _bytesRead >= _audioSize ? (_audioSize - alignment) : _bytesRead - (_bytesRead % alignment);
} break;
default:
break;
}
for (int i = 0; i < QUEUEBUFFER_NUM; i++) {
produceChunk();
}
}
}
void WAVReader::flushChunks()
{
_rwMutex.lock();
while (!_chnkQ.empty()) {
delete[] _chnkQ.front()._data;
_chnkQ.pop();
}
_rwMutex.unlock();
}
#endif

View File

@ -0,0 +1,109 @@
/*
* cocos2d-x http://www.cocos2d-x.org
*
* Copyright (c) 2010-2011 - cocos2d-x community
*
* Portions Copyright (c) Microsoft Open Technologies, Inc.
* All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
#ifndef __AUDIO_SOURCE_READER_H_
#define __AUDIO_SOURCE_READER_H_
#define NEAR near
#include "MediaStreamer.h"
NS_CC_BEGIN
namespace experimental{
const UINT PCMDATA_CACHEMAXSIZE = 2621440;
const UINT QUEUEBUFFER_NUM = 4;
const UINT CHUNK_SIZE_MAX = PCMDATA_CACHEMAXSIZE / QUEUEBUFFER_NUM;
enum class FileFormat
{
UNKNOWN,
WAV,
MP3,
OGG
};
typedef struct AudioDataChunk
{
size_t _dataSize;
unsigned char *_data;
bool _endOfStream;
int _seqNo;
} AudioDataChunk;
class AudioSourceReader
{
public:
AudioSourceReader();
virtual ~AudioSourceReader();
bool isStreamingSource() { return _isStreaming; }
std::string getFilePath() { return _filePath; }
virtual size_t getTotalAudioBytes() { return _audioSize; }
virtual bool initialize(const std::string& filePath) = 0;
virtual FileFormat getFileFormat() = 0;
virtual bool consumeChunk(AudioDataChunk& chunk) = 0;
virtual void produceChunk() = 0;
virtual void seekTo(const float ratio) = 0;
virtual const WAVEFORMATEX& getWaveFormatInfo() { return _wfx; }
protected:
bool _isStreaming;
std::string _filePath;
size_t _audioSize;
WAVEFORMATEX _wfx;
};
class WAVReader : public AudioSourceReader
{
public:
WAVReader();
~WAVReader();
bool initialize(const std::string& filePath) override;
FileFormat getFileFormat() override { return FileFormat::WAV; }
bool consumeChunk(AudioDataChunk& chunk) override;
void produceChunk() override;
void seekTo(const float ratio) override;
protected:
void enqueueChunk(const AudioDataChunk& chunk);
void flushChunks();
private:
bool _isDirty;
size_t _bytesRead;
std::mutex _rwMutex;
MediaStreamer^ _streamer;
std::queue<AudioDataChunk> _chnkQ;
};
class MP3Reader : public AudioSourceReader
{
};
}
NS_CC_END
#endif // __AUDIO_SOURCE_READER_H_
#endif

View File

@ -39,6 +39,8 @@ using namespace Concurrency;
((uint32)(byte)(ch2) << 16) | ((uint32)(byte)(ch3) << 24 ))
#endif /* defined(MAKEFOURCC) */
const int FMT_CHUNK_MAX = 256;
inline void ThrowIfFailed(HRESULT hr)
{
if (FAILED(hr))
@ -50,6 +52,8 @@ inline void ThrowIfFailed(HRESULT hr)
MediaStreamer::MediaStreamer() :
m_offset(0)
, m_dataLen(0)
, m_filename(nullptr)
{
ZeroMemory(&m_waveFormat, sizeof(m_waveFormat));
m_location = Package::Current->InstalledLocation;
@ -59,9 +63,13 @@ MediaStreamer::MediaStreamer() :
MediaStreamer::~MediaStreamer()
{
}
Platform::Array<byte>^ MediaStreamer::ReadData(
_In_ Platform::String^ filename
)
Platform::Array<byte>^ MediaStreamer::ReadData(_In_ Platform::String^ filename)
{
return ReadData(filename, 0, 0);
}
Platform::Array<byte>^ MediaStreamer::ReadData(_In_ Platform::String^ filename, uint32 from, uint32 length)
{
CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {0};
extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
@ -72,26 +80,16 @@ Platform::Array<byte>^ MediaStreamer::ReadData(
extendedParams.hTemplateFile = nullptr;
Wrappers::FileHandle file(
CreateFile2(
filename->Data(),
GENERIC_READ,
FILE_SHARE_READ,
OPEN_EXISTING,
&extendedParams
)
CreateFile2(filename->Data(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, &extendedParams)
);
if (file.Get()==INVALID_HANDLE_VALUE)
{
throw ref new Platform::FailureException();
}
FILE_STANDARD_INFO fileInfo = {0};
if (!GetFileInformationByHandleEx(
file.Get(),
FileStandardInfo,
&fileInfo,
sizeof(fileInfo)
))
FILE_STANDARD_INFO fileInfo = { 0 };
if (!GetFileInformationByHandleEx(file.Get(), FileStandardInfo, &fileInfo, sizeof(fileInfo)))
{
throw ref new Platform::FailureException();
}
@ -101,15 +99,21 @@ Platform::Array<byte>^ MediaStreamer::ReadData(
throw ref new Platform::OutOfMemoryException();
}
Platform::Array<byte>^ fileData = ref new Platform::Array<byte>(fileInfo.EndOfFile.LowPart);
from += m_offset;
length = (length == 0 || from + length > fileInfo.EndOfFile.LowPart) ? fileInfo.EndOfFile.LowPart - from : length;
Platform::Array<byte>^ fileData = ref new Platform::Array<byte>(length);
if (!ReadFile(
file.Get(),
fileData->Data,
fileData->Length,
nullptr,
nullptr
) )
if (from)
{
LARGE_INTEGER pos = { 0 };
pos.QuadPart = from;
if (!SetFilePointerEx(file.Get(), pos, nullptr, FILE_BEGIN))
{
throw ref new Platform::FailureException();
}
}
if (!ReadFile(file.Get(), fileData->Data, fileData->Length, nullptr, nullptr))
{
throw ref new Platform::FailureException();
}
@ -117,9 +121,9 @@ Platform::Array<byte>^ MediaStreamer::ReadData(
return fileData;
}
void MediaStreamer::Initialize(__in const WCHAR* url)
void MediaStreamer::Initialize(__in const WCHAR* url, bool lazy)
{
m_filename = ref new Platform::String(url);
WCHAR filePath[MAX_PATH] = {0};
if ((wcslen(url) > 1 && url[1] == ':'))
{
@ -139,8 +143,7 @@ void MediaStreamer::Initialize(__in const WCHAR* url)
wcscat_s(filePath, url);
}
Platform::Array<byte>^ data = ReadData(ref new Platform::String(filePath));
Platform::Array<byte>^ data = lazy ? ReadData(ref new Platform::String(filePath), 0, FMT_CHUNK_MAX) : ReadData(ref new Platform::String(filePath));
UINT32 length = data->Length;
const byte * dataPtr = data->Data;
UINT32 offset = 0;
@ -197,14 +200,25 @@ void MediaStreamer::Initialize(__in const WCHAR* url)
// Locate the 'data' chunk and copy its contents to a buffer.
ThrowIfFailed(ReadChunk(MAKEFOURCC('d', 'a', 't', 'a'), chunkSize, chunkPos));
m_dataLen = chunkSize;
m_offset = chunkPos;
if (!lazy)
{
m_data.resize(chunkSize);
CopyMemory(m_data.data(), &dataPtr[chunkPos], chunkSize);
m_offset = 0;
}
}
void MediaStreamer::ReadAll(uint8* buffer, uint32 maxBufferSize, uint32* bufferLength)
{
if (!m_data.size())
{
ReadChunk(buffer, 0, m_dataLen, bufferLength);
}
else
{
UINT32 toCopy = m_data.size() - m_offset;
if (toCopy > maxBufferSize) toCopy = maxBufferSize;
@ -213,6 +227,18 @@ void MediaStreamer::ReadAll(uint8* buffer, uint32 maxBufferSize, uint32* bufferL
m_offset += toCopy;
if (m_offset > m_data.size()) m_offset = m_data.size();
}
}
void MediaStreamer::ReadChunk(uint8* buffer, uint32 from, uint32 length, uint32* bytesRead)
{
Platform::Array<byte>^ data = ReadData(m_filename, from, length);
*bytesRead = data->Length;
if (*bytesRead > 0)
{
CopyMemory(buffer, (byte*)data->Data, data->Length);
}
}
void MediaStreamer::Restart()

View File

@ -29,9 +29,12 @@ private:
uint32 m_maxStreamLengthInBytes;
std::vector<byte> m_data;
UINT32 m_offset;
Platform::Array<byte>^ ReadData(
_In_ Platform::String^ filename
);
UINT32 m_dataLen;
Platform::String^ m_filename;
Platform::Array<byte>^ ReadData(_In_ Platform::String^ filename);
Platform::Array<byte>^ ReadData(_In_ Platform::String^ filename, uint32 from, uint32 length);
internal:
Windows::Storage::StorageFolder^ m_location;
Platform::String^ m_locationPath;
@ -49,10 +52,11 @@ internal:
UINT32 GetMaxStreamLengthInBytes()
{
return m_data.size();
return m_dataLen;
}
void Initialize(_In_ const WCHAR* url);
void Initialize(_In_ const WCHAR* url, bool lazy = false);
void ReadAll(uint8* buffer, uint32 maxBufferSize, uint32* bufferLength);
void ReadChunk(uint8* buffer, uint32 from, uint32 length, uint32* bytesRead);
void Restart();
};

View File

@ -18,10 +18,12 @@
#include "SimpleAudioEngine.h"
#include "Audio.h"
#include "cocos2d.h"
#include <map>
//#include "CCCommon.h"
using namespace std;
USING_NS_CC;
namespace CocosDenshion {
@ -81,7 +83,8 @@ void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
return;
}
sharedAudioController()->PlayBackgroundMusic(pszFilePath, bLoop);
string fullPath = CCFileUtils::getInstance()->fullPathForFilename(pszFilePath);
sharedAudioController()->PlayBackgroundMusic(fullPath.c_str(), bLoop);
}
void SimpleAudioEngine::stopBackgroundMusic(bool bReleaseData)
@ -121,8 +124,8 @@ bool SimpleAudioEngine::isBackgroundMusicPlaying()
unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop,float pitch, float pan, float gain)
{
unsigned int sound;
sharedAudioController()->PlaySoundEffect(pszFilePath, bLoop, sound);
// TODO: need to support playEffect parameters
string fullPath = CCFileUtils::getInstance()->fullPathForFilename(pszFilePath);
sharedAudioController()->PlaySoundEffect(fullPath.c_str(), bLoop, sound); // TODO: need to support playEffect parameters
return sound;
}
@ -133,7 +136,8 @@ void SimpleAudioEngine::stopEffect(unsigned int nSoundId)
void SimpleAudioEngine::preloadEffect(const char* pszFilePath)
{
sharedAudioController()->PreloadSoundEffect(pszFilePath);
string fullPath = CCFileUtils::getInstance()->fullPathForFilename(pszFilePath);
sharedAudioController()->PreloadSoundEffect(fullPath.c_str());
}
void SimpleAudioEngine::pauseEffect(unsigned int nSoundId)
@ -168,7 +172,8 @@ void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)
void SimpleAudioEngine::unloadEffect(const char* pszFilePath)
{
sharedAudioController()->UnloadSoundEffect(pszFilePath);
string fullPath = CCFileUtils::getInstance()->fullPathForFilename(pszFilePath);
sharedAudioController()->UnloadSoundEffect(fullPath.c_str());
}
//////////////////////////////////////////////////////////////////////////

View File

@ -354,10 +354,6 @@ bool Console::listenOnTCP(int port)
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
WSADATA wsaData;
n = WSAStartup(MAKEWORD(2, 2),&wsaData);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
CCLogIPAddresses();
#endif
#endif
if ( (n = getaddrinfo(nullptr, serv, &hints, &res)) != 0) {
@ -446,8 +442,11 @@ void Console::stop()
{
if( _running ) {
_endThread = true;
if (_thread.joinable())
{
_thread.join();
}
}
}
void Console::addCommand(const Command& cmd)
@ -1056,6 +1055,17 @@ void Console::addClient()
_maxfd = std::max(_maxfd,fd);
sendPrompt(fd);
/**
* A SIGPIPE is sent to a process if it tried to write to socket that had been shutdown for
* writing or isn't connected (anymore) on iOS.
*
* The default behaviour for this signal is to end the process.So we make the process ignore SIGPIPE.
*/
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
int set = 1;
setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
#endif
}
}
@ -1155,16 +1165,18 @@ void Console::loop()
/* Any message for the remote console ? send it! */
if( !_DebugStrings.empty() ) {
_DebugStringsMutex.lock();
for(const auto &str : _DebugStrings) {
for(const auto &fd : _fds) {
send(fd, str.c_str(), str.length(),0);
if (_DebugStringsMutex.try_lock())
{
for (const auto &str : _DebugStrings) {
for (auto fd : _fds) {
send(fd, str.c_str(), str.length(), 0);
}
}
_DebugStrings.clear();
_DebugStringsMutex.unlock();
}
}
}
// clean up: ignore stdin, stdout and stderr
for(const auto &fd: _fds )

View File

@ -81,12 +81,12 @@ public:
*
* @return The scroll data of x axis.
*/
inline float getScrollX() { return _scrollX; };
inline float getScrollX() const { return _scrollX; };
/** Get mouse scroll data of y axis.
*
* @return The scroll data of y axis.
*/
inline float getScrollY() { return _scrollY; };
inline float getScrollY() const { return _scrollY; };
/** Set the cursor position.
*
@ -118,19 +118,19 @@ public:
* @return The mouse button.
* @js getButton
*/
inline int getMouseButton() { return _mouseButton; };
inline int getMouseButton() const { return _mouseButton; };
/** Get the cursor position of x axis.
*
* @return The x coordinate of cursor position.
* @js getLocationX
*/
inline float getCursorX() { return _x; };
inline float getCursorX() const { return _x; };
/** Get the cursor position of y axis.
*
* @return The y coordinate of cursor position.
* @js getLocationY
*/
inline float getCursorY() { return _y; };
inline float getCursorY() const { return _y; };
/** Returns the current touch location in OpenGL coordinates.
*

View File

@ -0,0 +1,208 @@
/****************************************************************************
Copyright (c) 2013-2015 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 "CCNinePatchImageParser.h"
#include "platform/CCImage.h"
#include "base/CCDirector.h"
NS_CC_BEGIN
NinePatchImageParser::~NinePatchImageParser()
{
}
NinePatchImageParser::NinePatchImageParser(Image* image)
{
this->_image = image;
this->_imageFrame = Rect(0,0,image->getWidth(), image->getHeight());
CCASSERT(image->getRenderFormat()==Texture2D::PixelFormat::RGBA8888,
"unsupported format, currently only supports rgba8888");
this->_isRotated = false;
}
NinePatchImageParser::NinePatchImageParser(Image* image, const Rect& frame, bool rotated)
{
this->_image = image;
CCASSERT(image->getRenderFormat()==Texture2D::PixelFormat::RGBA8888,
"unsupported format, currently only supports rgba8888");
this->_imageFrame = frame;
this->_isRotated = rotated;
}
int NinePatchImageParser::getFrameHeight()const
{
if (_isRotated)
{
return _imageFrame.size.width;
}
return _imageFrame.size.height;
}
int NinePatchImageParser::getFrameWidth()const
{
if (_isRotated)
{
return _imageFrame.size.height;
}
return _imageFrame.size.width;
}
int NinePatchImageParser::getPixelOriginOffset(Direction direction)const
{
int imageWidth = _image->getWidth();
int frameWidth = this->getFrameWidth();
int topLineLeftOffset = (int)_imageFrame.origin.y * imageWidth * 4 + (int)_imageFrame.origin.x * 4;
if(direction == Direction::HORIZONTAL)
{
return topLineLeftOffset;
}
else
{
if(_isRotated)
{
return topLineLeftOffset + (frameWidth - 1) * 4;
}
else
{
return topLineLeftOffset;
}
}
}
Vec2 NinePatchImageParser::parseHorizontalMargin()const
{
unsigned char* data = _image->getData();
data = data + this->getPixelOriginOffset(Direction::HORIZONTAL);
unsigned char lastPixel = *(data + 3);
int x1 = 0;
int x2 = 0;
int length = _imageFrame.origin.x + this->getFrameWidth();
for(int i = (int)_imageFrame.origin.x; i <= length ; i++)
{
unsigned char pixel = *(data + (i - (int)_imageFrame.origin.x) * 4 +3);
if(pixel != lastPixel)
{
if (pixel > 0)
{
x1 = (i - (int)_imageFrame.origin.x);
}
else
{
x2 = (i - (int)_imageFrame.origin.x);
break;
}
}
lastPixel = pixel;
}
return Vec2(x1,x2);
}
Vec2 NinePatchImageParser::parseVerticalMargin()const
{
unsigned char* data = _image->getData();
int imageWidth = _image->getWidth();
int y1 = 0;
int y2 = 0;
data = data + this->getPixelOriginOffset(Direction::VERTICAL);
unsigned char lastPixel = *(data + 3);
int length = (int)(_imageFrame.origin.y + this->getFrameHeight());
for(int i = _imageFrame.origin.y; i <= length; i++)
{
unsigned char pixel = *(data + (i - (int)_imageFrame.origin.y) * imageWidth * 4 + 3);
if(pixel != lastPixel)
{
if(pixel > 0)
{
y1 = (i - (int)_imageFrame.origin.y);
}
else
{
y2 = (i - (int)_imageFrame.origin.y);
break;
}
}
lastPixel = pixel;
}
return Vec2(y1,y2);
}
Rect NinePatchImageParser::parseCapInset() const
{
Rect capInsets;
Vec2 horizontalLine = this->parseHorizontalMargin();
Vec2 verticalLine = this->parseVerticalMargin();
if(_isRotated)
{
capInsets = Rect(verticalLine.y,
_imageFrame.size.height - horizontalLine.y,
verticalLine.y - verticalLine.x,
horizontalLine.y - horizontalLine.x);
}
else
{
capInsets = Rect(horizontalLine.x,
verticalLine.x,
horizontalLine.y - horizontalLine.x,
verticalLine.y - verticalLine.x);
}
capInsets = Rect(capInsets.origin.x / CC_CONTENT_SCALE_FACTOR(),
capInsets.origin.y / CC_CONTENT_SCALE_FACTOR(),
capInsets.size.width / CC_CONTENT_SCALE_FACTOR(),
capInsets.size.height / CC_CONTENT_SCALE_FACTOR());
return capInsets;
}
void NinePatchImageParser::setSpriteFrameInfo( const cocos2d::Rect& frameRect, bool rotated )
{
this->_imageFrame = frameRect;
this->_isRotated = rotated;
}
bool NinePatchImageParser::isNinePatchImage(const std::string& filepath)
{
size_t length = filepath.length();
if(length <7 )
{
return false;
}
if(filepath.compare(length-6, 6, ".9.png") == 0)
{
return true;
}
else
{
return false;
}
}
NS_CC_END

View File

@ -0,0 +1,114 @@
/****************************************************************************
Copyright (c) 2013-2015 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 "platform/CCPlatformMacros.h"
#include "math/CCGeometry.h"
NS_CC_BEGIN
class Image;
class SpriteFrame;
/**
* A class for paring Android .9 patch image.
* For more about Android .9 patch image format, please refer to
* http://developer.android.com/tools/help/draw9patch.html
*
* The class could parse a single .9 patch image and produce the capInsets
* as well as a sprite atlas and store all the capInsets infos in a Texture2D.
* Note:
* - Currently only PixelFormat::RGBA8888 is supported.
* - TexturePacker Trim mode is not supported at the moment.
*/
class CC_DLL NinePatchImageParser
{
public:
/**
* Determines whether a filename contains ".9.png" suffix.
* @param filename A 9-patch image name.
*
* @return If the filename contains ".9.png", then return true, otherwise false.
*/
static bool isNinePatchImage(const std::string& filename);
/**
* Instantiate a NinePatchImageParser with a Image object.
*
* @param image A Image object pointer.
*
* @return A NinePatchImageParser instance.
*/
NinePatchImageParser(Image* image);
/**
* Instantiate a NinePatchImageParser with a Image object and the spriteFrame info.
* The spriteFrame contains the frame rect in the image atlas and whether it
* is rotated or not.
*
* @param image A Image object pointer.
* @param frameRect The sprite frame rect in the image atlas.
* @param ratated Whether is sprite frame is rotated in the image atlas.
*
* @return
*/
NinePatchImageParser(Image* image, const Rect& frameRect, bool ratated);
/**
* Change the sprite frame info.
* It is useful when parsing multiple sprite frame with only on NinePatchImageParser.
*
* @param frameRect The sprite frame rect in the image atlas.
* @param rotated Whether is sprite frame is rotated in the image atlas.
*/
void setSpriteFrameInfo(const Rect& frameRect, bool rotated);
/**
* Default destructor.
*/
virtual ~NinePatchImageParser();
/**
* Parsing the image data and extract the capInsets info.
* @return The capInsets Rect.
*/
Rect parseCapInset()const;
private:
enum class Direction
{
HORIZONTAL,
VERTICAL
};
int getPixelOriginOffset(Direction direction)const;
Vec2 parseHorizontalMargin()const;
Vec2 parseVerticalMargin()const;
int getFrameWidth()const;
int getFrameHeight()const;
Image* _image;
Rect _imageFrame;
bool _isRotated;
};
NS_CC_END

View File

@ -85,7 +85,7 @@ Properties::Properties(Data* data, ssize_t* dataIdx, const std::string& name, co
rewind();
}
Properties* Properties::createWithoutAutorelease(const std::string& url)
Properties* Properties::createNonRefCounted(const std::string& url)
{
if (url.size() == 0)
{
@ -419,24 +419,25 @@ signed char Properties::readChar()
char* Properties::readLine(char* output, int num)
{
int idx=0;
if (eof())
return nullptr;
// little optimization: avoid uneeded dereferences
ssize_t dataIdx = *_dataIdx;
const ssize_t dataIdx = *_dataIdx;
int i;
while (dataIdx<_data->_size && _data->_bytes[dataIdx]!='\n' && idx-1<num)
for (i=0; i<num && dataIdx+i < _data->_size; i++)
{
dataIdx++; idx++;
auto c = _data->_bytes[dataIdx+i];
if (c == '\n')
break;
output[i] = c;
}
memcpy(output, &_data->_bytes[*_dataIdx], idx);
output[idx] = '\0';
output[i] = '\0';
// restore value
*_dataIdx = dataIdx;
*_dataIdx = dataIdx+i;
return output;
}

View File

@ -105,7 +105,7 @@ class Data;
@verbatim
// Create the top-level Properties object.
Properties* properties = Properties::createWithoutAutorelease("example.properties");
Properties* properties = Properties::createNonRefCounted("example.properties");
// Retrieve the "spriteTexture" namespace.
Properties* spriteTexture = properties->getNamespace("spriteTexture");
@ -187,7 +187,7 @@ public:
* @return The created Properties or NULL if there was an error.
* @script{create}
*/
static Properties* createWithoutAutorelease(const std::string& url);
static Properties* createNonRefCounted(const std::string& url);
/**
* Destructor.
@ -579,7 +579,7 @@ private:
bool seekFromCurrent(int offset);
bool eof();
// Called after createWithoutAutorelease(); copies info from parents into derived namespaces.
// Called after createNonRefCounted(); copies info from parents into derived namespaces.
void resolveInheritance(const char* id = NULL);
// Called by resolveInheritance().

View File

@ -0,0 +1,334 @@
/****************************************************************************
Copyright (c) 2010-2012 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.
****************************************************************************/
#include "base/CCUserDefault.h"
#include "platform/CCCommon.h"
#include "base/base64.h"
#include "base/ccUtils.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
#include "CCWinRTUtils.h"
using namespace Windows::Storage;
using namespace Windows::Foundation;
using namespace std;
#define XML_FILE_NAME "UserDefault.xml"
NS_CC_BEGIN
/**
* WinRT implementation of UserDefault
*/
UserDefault* UserDefault::_userDefault = nullptr;
string UserDefault::_filePath = string("");
bool UserDefault::_isFilePathInitialized = false;
UserDefault::~UserDefault()
{
}
UserDefault::UserDefault()
{
}
Platform::Object^ getPlatformKeyValue(const char* pKey)
{
// check key
if (!pKey)
{
return nullptr;
}
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
auto key = PlatformStringFromString(pKey);
auto values = localSettings->Values;
if (values->HasKey(key))
{
return values->Lookup(key);
}
return nullptr;
}
void setPlatformKeyValue(const char* pKey, PropertyValue^ value)
{
// check key
if (!pKey)
{
return;
}
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
auto values = localSettings->Values;
values->Insert(PlatformStringFromString(pKey), value);
}
bool UserDefault::getBoolForKey(const char* pKey)
{
return getBoolForKey(pKey, false);
}
bool UserDefault::getBoolForKey(const char* pKey, bool defaultValue)
{
bool ret = defaultValue;
auto value = getPlatformKeyValue(pKey);
if (value)
{
ret = safe_cast<bool>(value);
}
return ret;
}
int UserDefault::getIntegerForKey(const char* pKey)
{
return getIntegerForKey(pKey, 0);
}
int UserDefault::getIntegerForKey(const char* pKey, int defaultValue)
{
int ret = defaultValue;
auto value = getPlatformKeyValue(pKey);
if (value)
{
ret = safe_cast<int>(value);
}
return ret;
}
float UserDefault::getFloatForKey(const char* pKey)
{
return getFloatForKey(pKey, 0.0f);
}
float UserDefault::getFloatForKey(const char* pKey, float defaultValue)
{
float ret = (float)getDoubleForKey(pKey, (double)defaultValue);
return ret;
}
double UserDefault::getDoubleForKey(const char* pKey)
{
return getDoubleForKey(pKey, 0.0);
}
double UserDefault::getDoubleForKey(const char* pKey, double defaultValue)
{
double ret = defaultValue;
auto value = getPlatformKeyValue(pKey);
if (value)
{
ret = safe_cast<double>(value);
}
return ret;
}
std::string UserDefault::getStringForKey(const char* pKey)
{
return getStringForKey(pKey, "");
}
string UserDefault::getStringForKey(const char* pKey, const std::string & defaultValue)
{
string ret = defaultValue;
auto value = getPlatformKeyValue(pKey);
if (value)
{
auto result = safe_cast<Platform::String^>(value);
ret = PlatformStringToString(result);
}
return ret;
}
Data UserDefault::getDataForKey(const char* pKey)
{
return getDataForKey(pKey, Data::Null);
}
Data UserDefault::getDataForKey(const char* pKey, const Data& defaultValue)
{
Data ret = defaultValue;
std::string encodedData = getStringForKey(pKey,"");
if (!encodedData.empty())
{
unsigned char* decodedData = nullptr;
int decodedDataLen = base64Decode((unsigned char*) encodedData.c_str(), (unsigned int) encodedData.length(), &decodedData);
if (decodedData && decodedDataLen > 0)
{
ret.fastSet(decodedData, decodedDataLen);
}
}
return ret;
}
void UserDefault::setBoolForKey(const char* pKey, bool value)
{
// check key
if (!pKey)
{
return;
}
setPlatformKeyValue(pKey, dynamic_cast<PropertyValue^>(PropertyValue::CreateBoolean(value)));
}
void UserDefault::setIntegerForKey(const char* pKey, int value)
{
// check key
if (! pKey)
{
return;
}
setPlatformKeyValue(pKey, dynamic_cast<PropertyValue^>(PropertyValue::CreateInt32(value)));
}
void UserDefault::setFloatForKey(const char* pKey, float value)
{
setDoubleForKey(pKey, value);
}
void UserDefault::setDoubleForKey(const char* pKey, double value)
{
// check key
if (! pKey)
{
return;
}
setPlatformKeyValue(pKey, dynamic_cast<PropertyValue^>(PropertyValue::CreateDouble(value)));
}
void UserDefault::setStringForKey(const char* pKey, const std::string & value)
{
// check key
if (! pKey)
{
return;
}
setPlatformKeyValue(pKey, dynamic_cast<PropertyValue^>(PropertyValue::CreateString(PlatformStringFromString(value))));
}
void UserDefault::setDataForKey(const char* pKey, const Data& value) {
// check key
if (! pKey)
{
return;
}
char *encodedData = 0;
base64Encode(value.getBytes(), static_cast<unsigned int>(value.getSize()), &encodedData);
setPlatformKeyValue(pKey, dynamic_cast<PropertyValue^>(PropertyValue::CreateString(PlatformStringFromString(encodedData))));
if (encodedData)
free(encodedData);
}
UserDefault* UserDefault::getInstance()
{
if (!_userDefault)
{
initXMLFilePath();
// only create xml file one time
// the file exists after the program exit
if ((!isXMLFileExist()) && (!createXMLFile()))
{
return nullptr;
}
_userDefault = new (std::nothrow) UserDefault();
}
return _userDefault;
}
void UserDefault::destroyInstance()
{
CC_SAFE_DELETE(_userDefault);
}
void UserDefault::setDelegate(UserDefault *delegate)
{
if (_userDefault)
delete _userDefault;
_userDefault = delegate;
}
// FIXME:: deprecated
UserDefault* UserDefault::sharedUserDefault()
{
return UserDefault::getInstance();
}
// FIXME:: deprecated
void UserDefault::purgeSharedUserDefault()
{
return UserDefault::destroyInstance();
}
bool UserDefault::isXMLFileExist()
{
//return FileUtils::getInstance()->isFileExist(_filePath);
return true;
}
void UserDefault::initXMLFilePath()
{
if (! _isFilePathInitialized)
{
_filePath += FileUtils::getInstance()->getWritablePath() + XML_FILE_NAME;
_isFilePathInitialized = true;
}
}
// create new xml file
bool UserDefault::createXMLFile()
{
return false;
}
const string& UserDefault::getXMLFilePath()
{
return _filePath;
}
void UserDefault::flush()
{
}
NS_CC_END
#endif // (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)

View File

@ -237,7 +237,7 @@ public:
* @js NA
*/
static const std::string& getXMLFilePath();
/** All supported platforms other iOS & Android use xml file to save values. This function checks whether the xml file exists or not.
/** All supported platforms other iOS & Android and CC_PLATFORM_WINRT use xml file to save values. This function checks whether the xml file exists or not.
* @return True if the xml file exists, flase if not.
* @js NA
*/

View File

@ -15,6 +15,7 @@ set(COCOS_BASE_SRC
base/CCController.cpp
base/CCData.cpp
base/CCDataVisitor.cpp
base/CCNinePatchImageParser.cpp
base/CCDirector.cpp
base/CCEvent.cpp
base/CCEventAcceleration.cpp

View File

@ -254,7 +254,8 @@ THE SOFTWARE.
/** Use 3d physics integration API. */
#ifndef CC_USE_3D_PHYSICS
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
#define CC_USE_3D_PHYSICS 1
#define CC_USE_3D_PHYSICS 1
#endif
#endif

View File

@ -183,7 +183,7 @@ ActionTimeline* ActionTimelineCache::loadAnimationActionWithContent(const std::s
doc.Parse<0>(content.c_str());
if (doc.HasParseError())
{
CCLOG("GetParseError %s\n", doc.GetParseError());
CCLOG("GetParseError %d\n", doc.GetParseError());
}
const rapidjson::Value& json = DICTOOL->getSubDictionary_json(doc, ACTION);

View File

@ -376,7 +376,7 @@ Node* CSLoader::loadNodeWithContent(const std::string& content)
doc.Parse<0>(content.c_str());
if (doc.HasParseError())
{
CCLOG("GetParseError %s\n", doc.GetParseError());
CCLOG("GetParseError %d\n", doc.GetParseError());
}
// cocos2dx version mono editor is based on
@ -724,7 +724,7 @@ Node* CSLoader::loadWidget(const rapidjson::Value& json)
customJsonDict.Parse<0>(customProperty);
if (customJsonDict.HasParseError())
{
CCLOG("GetParseError %s\n", customJsonDict.GetParseError());
CCLOG("GetParseError %d\n", customJsonDict.GetParseError());
}
widgetPropertiesReader->setPropsForAllCustomWidgetFromJsonDictionary(classname, widget, customJsonDict);

View File

@ -1247,7 +1247,7 @@ void DataReaderHelper::addDataFromJsonCache(const std::string& fileContent, Data
json.ParseStream<0>(stream);
if (json.HasParseError()) {
CCLOG("GetParseError %s\n",json.GetParseError());
CCLOG("GetParseError %d\n",json.GetParseError());
}
dataInfo->contentScale = DICTOOL->getFloatValue_json(json, CONTENT_SCALE, 1.0f);

View File

@ -212,7 +212,7 @@ Widget* GUIReader::widgetFromJsonFile(const char *fileName)
jsonDict.Parse<0>(contentStr.c_str());
if (jsonDict.HasParseError())
{
CCLOG("GetParseError %s\n",jsonDict.GetParseError());
CCLOG("GetParseError %d\n",jsonDict.GetParseError());
}
Widget* widget = nullptr;
const char* fileVersion = DICTOOL->getStringValue_json(jsonDict, "version");
@ -1373,7 +1373,7 @@ Widget* WidgetPropertiesReader0300::widgetFromBinary(CocoLoader* cocoLoader, st
customJsonDict.Parse<0>(customProperty);
if (customJsonDict.HasParseError())
{
CCLOG("GetParseError %s\n", customJsonDict.GetParseError());
CCLOG("GetParseError %d\n", customJsonDict.GetParseError());
}
setPropsForAllCustomWidgetFromJsonDictionary(classname, widget, customJsonDict);
}else{
@ -1474,7 +1474,7 @@ Widget* WidgetPropertiesReader0300::widgetFromJsonDictionary(const rapidjson::Va
customJsonDict.Parse<0>(customProperty);
if (customJsonDict.HasParseError())
{
CCLOG("GetParseError %s\n", customJsonDict.GetParseError());
CCLOG("GetParseError %d\n", customJsonDict.GetParseError());
}
setPropsForAllCustomWidgetFromJsonDictionary(classname, widget, customJsonDict);
}else{

View File

@ -236,7 +236,7 @@ void TriggerMng::buildJson(rapidjson::Document &document, cocostudio::CocoLoader
{
if (str2 != nullptr)
{
action.AddMember("classname", str2, allocator);
action.AddMember("classname", rapidjson::Value(str2,allocator), allocator);
}
}
else if (key2.compare("dataitems") == 0)
@ -257,7 +257,7 @@ void TriggerMng::buildJson(rapidjson::Document &document, cocostudio::CocoLoader
{
if (str3 != nullptr)
{
dataitem.AddMember("key", str3, allocator);
dataitem.AddMember("key", rapidjson::Value(str3,allocator), allocator);
}
}
else
@ -265,7 +265,7 @@ void TriggerMng::buildJson(rapidjson::Document &document, cocostudio::CocoLoader
rapidjson::Type type = pDataItemArray[i5].GetType(pCocoLoader);
if (type == rapidjson::kStringType)
{
dataitem.AddMember("value", str3, allocator);
dataitem.AddMember("value", rapidjson::Value(str3,allocator), allocator);
}
else
{
@ -312,7 +312,7 @@ void TriggerMng::buildJson(rapidjson::Document &document, cocostudio::CocoLoader
{
if (str4 != nullptr)
{
cond.AddMember("classname", str4, allocator);
cond.AddMember("classname", rapidjson::Value(str4,allocator), allocator);
}
}
else if (key4.compare("dataitems") == 0)
@ -333,7 +333,7 @@ void TriggerMng::buildJson(rapidjson::Document &document, cocostudio::CocoLoader
{
if (str5 != nullptr)
{
dataitem.AddMember("key", str5, allocator);
dataitem.AddMember("key", rapidjson::Value(str5,allocator), allocator);
}
}
else
@ -341,7 +341,7 @@ void TriggerMng::buildJson(rapidjson::Document &document, cocostudio::CocoLoader
rapidjson::Type type = pDataItemArray[i9].GetType(pCocoLoader);
if (type == rapidjson::kStringType)
{
dataitem.AddMember("value", str5, allocator);
dataitem.AddMember("value", rapidjson::Value(str5,allocator), allocator);
}
else
{

View File

@ -154,12 +154,12 @@ void ArmatureNodeReader::setPropsWithFlatBuffers(cocos2d::Node *node,
fileExist = false;
}
if (!fileExist)
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", filepath.c_str())->getCString());
custom->addChild(label);
}
//if (!fileExist)
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", filepath.c_str())->getCString());
// custom->addChild(label);
//}
}

View File

@ -706,12 +706,12 @@ namespace cocostudio
{
button->loadTextureNormal(normalTexturePath, (Widget::TextureResType)normalType);
}
else if (!normalTexturePath.empty())
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", normalErrorFilePath.c_str())->getCString());
button->addChild(label);
}
//else if (!normalTexturePath.empty())
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", normalErrorFilePath.c_str())->getCString());
// button->addChild(label);
//}
bool pressedFileExist = false;
std::string pressedErrorFilePath = "";
@ -770,12 +770,12 @@ namespace cocostudio
{
button->loadTexturePressed(pressedTexturePath, (Widget::TextureResType)pressedType);
}
else if (!pressedTexturePath.empty())
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", pressedErrorFilePath.c_str())->getCString());
button->addChild(label);
}
//else if (!pressedTexturePath.empty())
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", pressedErrorFilePath.c_str())->getCString());
// button->addChild(label);
//}
bool disabledFileExist = false;
std::string disabledErrorFilePath = "";
@ -834,12 +834,12 @@ namespace cocostudio
{
button->loadTextureDisabled(disabledTexturePath, (Widget::TextureResType)disabledType);
}
else if (!disabledTexturePath.empty())
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", disabledErrorFilePath.c_str())->getCString());
button->addChild(label);
}
//else if (!disabledTexturePath.empty())
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", disabledErrorFilePath.c_str())->getCString());
// button->addChild(label);
//}
std::string titleText = options->text()->c_str();
button->setTitleText(titleText);
@ -873,12 +873,12 @@ namespace cocostudio
{
button->setTitleFontName(path);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
button->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// button->addChild(label);
//}
}
bool displaystate = options->displaystate() != 0;

View File

@ -491,12 +491,12 @@ namespace cocostudio
{
checkBox->loadTextureBackGround(backGroundTexturePath, (Widget::TextureResType)backGroundType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", backGroundErrorFilePath.c_str())->getCString());
checkBox->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", backGroundErrorFilePath.c_str())->getCString());
// checkBox->addChild(label);
//}
//load background selected image
bool backGroundSelectedfileExist = false;
@ -556,12 +556,12 @@ namespace cocostudio
{
checkBox->loadTextureBackGroundSelected(backGroundSelectedTexturePath, (Widget::TextureResType)backGroundSelectedType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", backGroundSelectedErrorFilePath.c_str())->getCString());
checkBox->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", backGroundSelectedErrorFilePath.c_str())->getCString());
// checkBox->addChild(label);
//}
//load frontCross image
bool frontCrossFileExist = false;
@ -621,12 +621,12 @@ namespace cocostudio
{
checkBox->loadTextureFrontCross(frontCrossFileName, (Widget::TextureResType)frontCrossType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", frontCrossErrorFilePath.c_str())->getCString());
checkBox->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", frontCrossErrorFilePath.c_str())->getCString());
// checkBox->addChild(label);
//}
//load backGroundBoxDisabledData
bool backGroundBoxDisabledFileExist = false;
@ -686,12 +686,12 @@ namespace cocostudio
{
checkBox->loadTextureBackGroundDisabled(backGroundDisabledFileName, (Widget::TextureResType)backGroundDisabledType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", backGroundBoxDisabledErrorFilePath.c_str())->getCString());
checkBox->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", backGroundBoxDisabledErrorFilePath.c_str())->getCString());
// checkBox->addChild(label);
//}
///load frontCrossDisabledData
bool frontCrossDisabledFileExist = false;
@ -751,12 +751,12 @@ namespace cocostudio
{
checkBox->loadTextureFrontCrossDisabled(frontCrossDisabledFileName, (Widget::TextureResType)frontCrossDisabledType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", frontCrossDisabledErrorFilePath.c_str())->getCString());
checkBox->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", frontCrossDisabledErrorFilePath.c_str())->getCString());
// checkBox->addChild(label);
//}
bool selectedstate = options->selectedState() != 0;
checkBox->setSelected(selectedstate);

View File

@ -238,15 +238,15 @@ namespace cocostudio
setPropsWithFlatBuffers(tmx, (Table*)gameMapOptions);
}
}
else
{
Node* node = Node::create();
setPropsWithFlatBuffers(node, (Table*)gameMapOptions);
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
node->addChild(label);
return node;
}
//else
//{
// Node* node = Node::create();
// setPropsWithFlatBuffers(node, (Table*)gameMapOptions);
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// node->addChild(label);
// return node;
//}
return tmx;
}

View File

@ -353,12 +353,12 @@ namespace cocostudio
{
imageView->loadTexture(imageFileName, (Widget::TextureResType)imageFileNameType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
imageView->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// imageView->addChild(label);
//}
bool scale9Enabled = options->scale9Enabled() != 0;
imageView->setScale9Enabled(scale9Enabled);

View File

@ -190,10 +190,13 @@ namespace cocostudio
/* adapt screen gui */
float w = 0, h = 0;
bool adaptScrennExsit = DICTOOL->checkObjectExist_json(options, P_AdaptScreen);
if (adaptScrennExsit)
{
bool adaptScrenn = DICTOOL->getBooleanValue_json(options, P_AdaptScreen);
if (adaptScrenn)
{
Size screenSize = CCDirector::getInstance()->getWinSize();
Size screenSize = Director::getInstance()->getWinSize();
w = screenSize.width;
h = screenSize.height;
}
@ -202,6 +205,12 @@ namespace cocostudio
w = DICTOOL->getFloatValue_json(options, P_Width);
h = DICTOOL->getFloatValue_json(options, P_Height);
}
}
else
{
w = DICTOOL->getFloatValue_json(options, P_Width);
h = DICTOOL->getFloatValue_json(options, P_Height);
}
panel->setContentSize(Size(w, h));
/**/
@ -300,7 +309,11 @@ namespace cocostudio
panel->setBackGroundImageCapInsets(Rect(cx, cy, cw, ch));
}
bool layoutTypeExsit = DICTOOL->checkObjectExist_json(options, P_LayoutType);
if (layoutTypeExsit)
{
panel->setLayoutType((Layout::Type)DICTOOL->getIntValue_json(options, P_LayoutType));
}
int bgimgcr = DICTOOL->getIntValue_json(options, P_ColorR,255);
int bgimgcg = DICTOOL->getIntValue_json(options, P_ColorG,255);
@ -662,12 +675,12 @@ namespace cocostudio
{
panel->setBackGroundImage(imageFileName, (Widget::TextureResType)imageFileNameType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
panel->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// panel->addChild(label);
//}
}
auto widgetOptions = options->widgetOptions();

View File

@ -490,12 +490,12 @@ namespace cocostudio
{
listView->setBackGroundImage(imageFileName, (Widget::TextureResType)imageFileNameType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
listView->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// listView->addChild(label);
//}
}
auto widgetOptions = options->widgetOptions();

View File

@ -303,12 +303,12 @@ namespace cocostudio
{
loadingBar->loadTexture(imageFileName, (Widget::TextureResType)imageFileNameType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
loadingBar->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// loadingBar->addChild(label);
//}
int direction = options->direction();
loadingBar->setDirection(LoadingBar::Direction(direction));

View File

@ -403,12 +403,12 @@ namespace cocostudio
{
pageView->setBackGroundImage(imageFileName, (Widget::TextureResType)imageFileNameType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
pageView->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// pageView->addChild(label);
//}
}
auto widgetOptions = options->widgetOptions();

View File

@ -208,15 +208,15 @@ namespace cocostudio
particle->setPositionType(ParticleSystem::PositionType::GROUPED);
}
}
else
{
Node* node = Node::create();
setPropsWithFlatBuffers(node, (Table*)particleOptions);
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
node->addChild(label);
return node;
}
//else
//{
// Node* node = Node::create();
// setPropsWithFlatBuffers(node, (Table*)particleOptions);
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// node->addChild(label);
// return node;
//}
return particle;
}

View File

@ -489,12 +489,12 @@ namespace cocostudio
{
scrollView->setBackGroundImage(imageFileName, (Widget::TextureResType)imageFileNameType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
scrollView->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// scrollView->addChild(label);
//}
}
auto widgetOptions = options->widgetOptions();

View File

@ -525,12 +525,12 @@ namespace cocostudio
{
slider->loadBarTexture(imageFileName, (Widget::TextureResType)imageFileNameType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", imageErrorFilePath.c_str())->getCString());
slider->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", imageErrorFilePath.c_str())->getCString());
// slider->addChild(label);
//}
//loading normal slider ball texture
bool normalFileExist = false;
@ -590,12 +590,12 @@ namespace cocostudio
{
slider->loadSlidBallTextureNormal(normalFileName, (Widget::TextureResType)normalType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", normalErrorFilePath.c_str())->getCString());
slider->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", normalErrorFilePath.c_str())->getCString());
// slider->addChild(label);
//}
//loading slider ball press texture
bool pressedFileExist = false;
@ -655,12 +655,12 @@ namespace cocostudio
{
slider->loadSlidBallTexturePressed(pressedFileName, (Widget::TextureResType)pressedType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", pressedErrorFilePath.c_str())->getCString());
slider->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", pressedErrorFilePath.c_str())->getCString());
// slider->addChild(label);
//}
//loading silder ball disable texture
bool disabledFileExist = false;
@ -720,12 +720,12 @@ namespace cocostudio
{
slider->loadSlidBallTextureDisabled(disabledFileName, (Widget::TextureResType)disabledType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", disabledErrorFilePath.c_str())->getCString());
slider->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", disabledErrorFilePath.c_str())->getCString());
// slider->addChild(label);
//}
//load slider progress texture
bool progressFileExist = false;
@ -785,12 +785,12 @@ namespace cocostudio
{
slider->loadProgressBarTexture(progressBarFileName, (Widget::TextureResType)progressBarType);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", progressErrorFilePath.c_str())->getCString());
slider->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", progressErrorFilePath.c_str())->getCString());
// slider->addChild(label);
//}
bool displaystate = options->displaystate() != 0;
slider->setBright(displaystate);

View File

@ -226,12 +226,12 @@ namespace cocostudio
default:
break;
}
if (!fileExist)
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
sprite->addChild(label);
}
//if (!fileExist)
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// sprite->addChild(label);
//}
auto f_blendFunc = options->blendFunc();
if (f_blendFunc)

View File

@ -275,12 +275,12 @@ namespace cocostudio
fileExist = false;
}
if (!fileExist)
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
labelAtlas->addChild(label);
}
//if (!fileExist)
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// labelAtlas->addChild(label);
//}
break;
}

View File

@ -218,11 +218,11 @@ namespace cocostudio
fileExist = false;
}
}
else
{
errorContent = "missed";
fileExist = false;
}
//else
//{
// errorContent = "missed";
// fileExist = false;
//}
break;
}
@ -234,12 +234,15 @@ namespace cocostudio
labelBMFont->setFntFile(path);
}
else
{
if (!errorContent.empty())
{
errorFilePath = path;
auto label = Label::create();
label->setString(__String::createWithFormat("%s %s", errorFilePath.c_str(), errorContent.c_str())->getCString());
labelBMFont->addChild(label);
}
}
std::string text = options->text()->c_str();
labelBMFont->setString(text);

View File

@ -332,12 +332,12 @@ namespace cocostudio
{
textField->setFontName(path);
}
else
{
auto label = Label::create();
label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
textField->addChild(label);
}
//else
//{
// auto label = Label::create();
// label->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// textField->addChild(label);
//}
}
auto widgetReader = WidgetReader::getInstance();

View File

@ -440,12 +440,12 @@ namespace cocostudio
{
label->setFontName(path);
}
else
{
auto alert = Label::create();
alert->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
label->addChild(alert);
}
//else
//{
// auto alert = Label::create();
// alert->setString(__String::createWithFormat("%s missed", errorFilePath.c_str())->getCString());
// label->addChild(alert);
//}
}
bool outlineEnabled = options->outlineEnabled();

View File

@ -160,10 +160,13 @@ namespace cocostudio
/* adapt screen */
float w = 0, h = 0;
bool adaptScrennExsit = DICTOOL->checkObjectExist_json(options, P_AdaptScreen);
if (adaptScrennExsit)
{
bool adaptScrenn = DICTOOL->getBooleanValue_json(options, P_AdaptScreen);
if (adaptScrenn)
{
Size screenSize = CCDirector::getInstance()->getWinSize();
Size screenSize = Director::getInstance()->getWinSize();
w = screenSize.width;
h = screenSize.height;
}
@ -172,6 +175,13 @@ namespace cocostudio
w = DICTOOL->getFloatValue_json(options, P_Width);
h = DICTOOL->getFloatValue_json(options, P_Height);
}
}
else
{
w = DICTOOL->getFloatValue_json(options, P_Width);
h = DICTOOL->getFloatValue_json(options, P_Height);
}
widget->setContentSize(Size(w, h));
widget->setTag(DICTOOL->getIntValue_json(options, P_Tag));

View File

@ -128,6 +128,7 @@
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_LIB;COCOS2DXWIN32_EXPORTS;GL_GLEXT_PROTOTYPES;COCOS2D_DEBUG=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\angle\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -145,6 +146,7 @@
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;_WINDOWS;_LIB;COCOS2DXWIN32_EXPORTS;GL_GLEXT_PROTOTYPES;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\angle\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -162,6 +164,7 @@
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_LIB;COCOS2DXWIN32_EXPORTS;GL_GLEXT_PROTOTYPES;COCOS2D_DEBUG=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\angle\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -179,6 +182,7 @@
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;_WINDOWS;_LIB;COCOS2DXWIN32_EXPORTS;GL_GLEXT_PROTOTYPES;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\angle\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -196,6 +200,7 @@
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_LIB;COCOS2DXWIN32_EXPORTS;GL_GLEXT_PROTOTYPES;COCOS2D_DEBUG=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\angle\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -213,6 +218,7 @@
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;_WINDOWS;_LIB;COCOS2DXWIN32_EXPORTS;GL_GLEXT_PROTOTYPES;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(EngineRoot)external\winrt_8.1-specific\angle\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

View File

@ -93,6 +93,7 @@
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_LIB;COCOS2DXWIN32_EXPORTS;GL_GLEXT_PROTOTYPES;COCOS2D_DEBUG=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(EngineRoot)external\wp_8.1-specific\angle\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -110,6 +111,7 @@
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;_WINDOWS;_LIB;COCOS2DXWIN32_EXPORTS;GL_GLEXT_PROTOTYPES;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(EngineRoot)external\wp_8.1-specific\angle\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -127,6 +129,7 @@
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_LIB;COCOS2DXWIN32_EXPORTS;GL_GLEXT_PROTOTYPES;COCOS2D_DEBUG=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(EngineRoot)external\wp_8.1-specific\angle\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -144,6 +147,7 @@
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;_WINDOWS;_LIB;COCOS2DXWIN32_EXPORTS;GL_GLEXT_PROTOTYPES;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(EngineRoot)external\wp_8.1-specific\angle\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

View File

@ -26,17 +26,12 @@
#include "HttpClient.h"
#include <thread>
#include <queue>
#include <sstream>
#include <condition_variable>
#include <stdio.h>
#include <errno.h>
#include "base/CCVector.h"
#include "base/CCDirector.h"
#include "base/CCScheduler.h"
#include "platform/CCFileUtils.h"
#include "platform/android/jni/JniHelper.h"
@ -49,24 +44,7 @@ typedef HttpRequestHeaders::iterator HttpRequestHeadersIter;
typedef std::vector<std::string> HttpCookies;
typedef HttpCookies::iterator HttpCookiesIter;
static std::mutex s_requestQueueMutex;
static std::mutex s_responseQueueMutex;
static std::mutex s_cookieFileMutex;
static std::condition_variable_any s_sleepCondition;
static Vector<HttpRequest*>* s_requestQueue = nullptr;
static Vector<HttpResponse*>* s_responseQueue = nullptr;
static HttpClient *s_httpClient = nullptr; // pointer to singleton
static std::string s_responseMessage = "";
static std::string s_cookieFilename = "";
static std::string s_sslCaFilename = "";
static HttpRequest *s_requestSentinel = new HttpRequest;
static HttpClient* _httpClient = nullptr; // pointer to singleton
struct CookiesInfo
@ -98,16 +76,16 @@ size_t writeHeaderData(void* buffer, size_t sizes,HttpResponse* response)
return sizes;
}
static void processResponse(HttpResponse* response, std::string& responseMessage);
class HttpURLConnection
{
public:
HttpURLConnection():_httpURLConnection(nullptr),
_requestmethod(""),
_responseCookies(""),
_cookieFileName(""),
_contentLength(0)
HttpURLConnection(HttpClient* httpClient)
:_httpURLConnection(nullptr)
,_client(httpClient)
,_requestmethod("")
,_responseCookies("")
,_cookieFileName("")
,_contentLength(0)
{
}
@ -139,7 +117,9 @@ public:
{
createHttpURLConnection(request->getUrl());
if(!configure())
{
return false;
}
/* get custom header data (if set) */
HttpRequestHeaders headers=request->getHeaders();
if(!headers.empty())
@ -259,15 +239,15 @@ public:
size_t saveResponseCookies(const char* responseCookies, size_t count)
{
if (nullptr == responseCookies || strlen(responseCookies) == 0 || count == 0)
{
return 0;
}
if (_cookieFileName.empty())
{
_cookieFileName = FileUtils::getInstance()->getWritablePath() + "cookieFile.txt";
}
std::lock_guard<std::mutex> lock(s_cookieFileMutex);
FILE* fp = fopen(_cookieFileName.c_str(), "w");
if (nullptr == fp)
{
@ -307,7 +287,9 @@ public:
char* getResponseContent(HttpResponse* response)
{
if (nullptr == response)
{
return nullptr;
}
char* content = nullptr;
JniMethodInfo methodInfo;
@ -447,14 +429,14 @@ private:
void addCookiesForRequestHeader()
{
if(s_cookieFilename.empty())
if(_client->getCookieFilename().empty())
{
return;
}
_cookieFileName = FileUtils::getInstance()->fullPathForFilename(s_cookieFilename.c_str());
_cookieFileName = FileUtils::getInstance()->fullPathForFilename(_client->getCookieFilename());
std::lock_guard<std::mutex> lock(s_cookieFileMutex);
std::string cookiesInfo = FileUtils::getInstance()->getStringFromFile(_cookieFileName.c_str());
std::string cookiesInfo = FileUtils::getInstance()->getStringFromFile(_cookieFileName);
if (cookiesInfo.empty())
return;
@ -550,10 +532,10 @@ private:
void setVerifySSL()
{
if(s_sslCaFilename.empty())
if(_client->getSSLVerification().empty())
return;
std::string fullpath = FileUtils::getInstance()->fullPathForFilename(s_sslCaFilename.c_str());
std::string fullpath = FileUtils::getInstance()->fullPathForFilename(_client->getSSLVerification());
JniMethodInfo methodInfo;
if (JniHelper::getStaticMethodInfo(methodInfo,
@ -572,13 +554,16 @@ private:
bool configure()
{
if(nullptr == _httpURLConnection)
{
return false;
}
HttpClient* instnace = HttpClient::getInstance();
if(nullptr == instnace)
if(nullptr == _client)
{
return false;
}
setReadAndConnectTimeout(instnace->getTimeoutForRead() * 1000, instnace->getTimeoutForConnect() * 1000);
setReadAndConnectTimeout(_client->getTimeoutForRead() * 1000, _client->getTimeoutForConnect() * 1000);
setVerifySSL();
@ -628,6 +613,7 @@ private:
return _responseCookies;
}
private:
HttpClient* _client;
jobject _httpURLConnection;
std::string _requestmethod;
std::string _responseCookies;
@ -637,7 +623,7 @@ private:
};
// Process Response
static void processResponse(HttpResponse* response, std::string& responseMessage)
void HttpClient::processResponse(HttpResponse* response, char* responseMessage)
{
auto request = response->getHttpRequest();
HttpRequest::Type requestType = request->getRequestType();
@ -654,7 +640,7 @@ static void processResponse(HttpResponse* response, std::string& responseMessage
long responseCode = -1;
int retValue = 0;
HttpURLConnection urlConnection;
HttpURLConnection urlConnection(this);
if(!urlConnection.init(request))
{
response->setSucceed(false);
@ -718,15 +704,15 @@ static void processResponse(HttpResponse* response, std::string& responseMessage
//content len
int contentLength = urlConnection.getResponseHeaderByKeyInt("Content-Length");
char* contentInfo = urlConnection.getResponseContent(response);
if (nullptr != contentInfo) {
// response->setResponseDataString(contentInfo, contentLength);
if (nullptr != contentInfo)
{
std::vector<char> * recvBuffer = (std::vector<char>*)response->getResponseData();
recvBuffer->clear();
recvBuffer->insert(recvBuffer->begin(), (char*)contentInfo, ((char*)contentInfo) + urlConnection.getContentLength());
}
free(contentInfo);
responseMessage = urlConnection.getResponseMessage();
strcpy(responseMessage, urlConnection.getResponseMessage());
urlConnection.disconnect();
// write data to HttpResponse
@ -735,7 +721,7 @@ static void processResponse(HttpResponse* response, std::string& responseMessage
if (responseCode == -1)
{
response->setSucceed(false);
response->setErrorBuffer(responseMessage.c_str());
response->setErrorBuffer(responseMessage);
}
else
{
@ -746,7 +732,7 @@ static void processResponse(HttpResponse* response, std::string& responseMessage
// Worker thread
void HttpClient::networkThread()
{
auto scheduler = Director::getInstance()->getScheduler();
increaseThreadCount();
while (true)
{
@ -754,133 +740,170 @@ void HttpClient::networkThread()
// step 1: send http request if the requestQueue isn't empty
{
std::lock_guard<std::mutex> lock(s_requestQueueMutex);
while (s_requestQueue->empty()) {
s_sleepCondition.wait(s_requestQueueMutex);
std::lock_guard<std::mutex> lock(_requestQueueMutex);
while (_requestQueue.empty()) {
_sleepCondition.wait(_requestQueueMutex);
}
request = s_requestQueue->at(0);
s_requestQueue->erase(0);
request = _requestQueue.at(0);
_requestQueue.erase(0);
}
if (request == s_requestSentinel) {
if (request == _requestSentinel) {
break;
}
// Create a HttpResponse object, the default setting is http access failed
HttpResponse *response = new (std::nothrow) HttpResponse(request);
processResponse(response, s_responseMessage);
processResponse(response, _responseMessage);
// add response packet into queue
s_responseQueueMutex.lock();
s_responseQueue->pushBack(response);
s_responseQueueMutex.unlock();
_responseQueueMutex.lock();
_responseQueue.pushBack(response);
_responseQueueMutex.unlock();
if (nullptr != s_httpClient) {
scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this));
_schedulerMutex.lock();
if (nullptr != _scheduler)
{
_scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this));
}
_schedulerMutex.unlock();
}
// cleanup: if worker thread received quit signal, clean up un-completed request queue
s_requestQueueMutex.lock();
s_requestQueue->clear();
s_requestQueueMutex.unlock();
_requestQueueMutex.lock();
_requestQueue.clear();
_requestQueueMutex.unlock();
_responseQueueMutex.lock();
_responseQueue.clear();
_responseQueueMutex.unlock();
if (s_requestQueue != nullptr) {
delete s_requestQueue;
s_requestQueue = nullptr;
delete s_responseQueue;
s_responseQueue = nullptr;
}
decreaseThreadCountAndMayDeleteThis();
}
// Worker thread
void HttpClient::networkThreadAlone(HttpRequest* request, HttpResponse* response)
{
std::string responseMessage = "";
increaseThreadCount();
char responseMessage[RESPONSE_BUFFER_SIZE] = { 0 };
processResponse(response, responseMessage);
auto scheduler = Director::getInstance()->getScheduler();
scheduler->performFunctionInCocosThread([response, request]{
_schedulerMutex.lock();
if (_scheduler != nullptr)
{
_scheduler->performFunctionInCocosThread([this, response, request]{
const ccHttpRequestCallback& callback = request->getCallback();
Ref* pTarget = request->getTarget();
SEL_HttpResponse pSelector = request->getSelector();
if (callback != nullptr)
{
callback(s_httpClient, response);
callback(this, response);
}
else if (pTarget && pSelector)
{
(pTarget->*pSelector)(s_httpClient, response);
(pTarget->*pSelector)(this, response);
}
response->release();
// do not release in other thread
request->release();
});
}
_schedulerMutex.unlock();
decreaseThreadCountAndMayDeleteThis();
}
// HttpClient implementation
HttpClient* HttpClient::getInstance()
{
if (s_httpClient == nullptr) {
s_httpClient = new (std::nothrow) HttpClient();
if (_httpClient == nullptr)
{
_httpClient = new (std::nothrow) HttpClient();
}
return s_httpClient;
return _httpClient;
}
void HttpClient::destroyInstance()
{
CC_SAFE_DELETE(s_httpClient);
if (_httpClient == nullptr)
{
CCLOG("HttpClient singleton is nullptr");
return;
}
CCLOG("HttpClient::destroyInstance ...");
auto thiz = _httpClient;
_httpClient = nullptr;
thiz->_scheduler->unscheduleAllForTarget(thiz);
thiz->_schedulerMutex.lock();
thiz->_scheduler = nullptr;
thiz->_schedulerMutex.unlock();
{
std::lock_guard<std::mutex> lock(thiz->_requestQueueMutex);
thiz->_requestQueue.pushBack(thiz->_requestSentinel);
}
thiz->_sleepCondition.notify_one();
thiz->decreaseThreadCountAndMayDeleteThis();
CCLOG("HttpClient::destroyInstance() finished!");
}
void HttpClient::enableCookies(const char* cookieFile) {
if (cookieFile) {
s_cookieFilename = std::string(cookieFile);
void HttpClient::enableCookies(const char* cookieFile)
{
std::lock_guard<std::mutex> lock(_cookieFileMutex);
if (cookieFile)
{
_cookieFilename = std::string(cookieFile);
}
else {
s_cookieFilename = (FileUtils::getInstance()->getWritablePath() + "cookieFile.txt");
else
{
_cookieFilename = (FileUtils::getInstance()->getWritablePath() + "cookieFile.txt");
}
}
void HttpClient::setSSLVerification(const std::string& caFile)
{
s_sslCaFilename = caFile;
std::lock_guard<std::mutex> lock(_sslCaFileMutex);
_sslCaFilename = caFile;
}
HttpClient::HttpClient()
: _timeoutForConnect(30)
, _timeoutForRead(60)
, _isInited(false)
, _threadCount(0)
, _requestSentinel(new HttpRequest())
, _cookie(nullptr)
{
CCLOG("In the constructor of HttpClient!");
increaseThreadCount();
_scheduler = Director::getInstance()->getScheduler();
}
HttpClient::~HttpClient()
{
if (s_requestQueue != nullptr) {
{
std::lock_guard<std::mutex> lock(s_requestQueueMutex);
s_requestQueue->pushBack(s_requestSentinel);
}
s_sleepCondition.notify_one();
}
s_httpClient = nullptr;
CCLOG("In the destructor of HttpClient!");
CC_SAFE_DELETE(_requestSentinel);
}
//Lazy create semaphore & mutex & thread
bool HttpClient::lazyInitThreadSemphore()
{
if (s_requestQueue != nullptr) {
if (_isInited)
{
return true;
} else {
s_requestQueue = new (std::nothrow) Vector<HttpRequest*>();
s_responseQueue = new (std::nothrow) Vector<HttpResponse*>();
}
else
{
auto t = std::thread(CC_CALLBACK_0(HttpClient::networkThread, this));
t.detach();
_isInited = true;
}
return true;
@ -889,31 +912,29 @@ bool HttpClient::lazyInitThreadSemphore()
//Add a get task to queue
void HttpClient::send(HttpRequest* request)
{
if (false == lazyInitThreadSemphore())
if (!lazyInitThreadSemphore())
{
return;
}
if (!request)
if (nullptr == request)
{
return;
}
request->retain();
if (nullptr != s_requestQueue) {
s_requestQueueMutex.lock();
s_requestQueue->pushBack(request);
s_requestQueueMutex.unlock();
_requestQueueMutex.lock();
_requestQueue.pushBack(request);
_requestQueueMutex.unlock();
// Notify thread start to work
s_sleepCondition.notify_one();
}
_sleepCondition.notify_one();
}
void HttpClient::sendImmediate(HttpRequest* request)
{
if(!request)
if(nullptr == request)
{
return;
}
@ -931,20 +952,17 @@ void HttpClient::dispatchResponseCallbacks()
{
// log("CCHttpClient::dispatchResponseCallbacks is running");
//occurs when cocos thread fires but the network thread has already quited
if (nullptr == s_responseQueue) {
return;
}
HttpResponse* response = nullptr;
s_responseQueueMutex.lock();
_responseQueueMutex.lock();
if (!s_responseQueue->empty())
if (!_responseQueue.empty())
{
response = s_responseQueue->at(0);
s_responseQueue->erase(0);
response = _responseQueue.at(0);
_responseQueue.erase(0);
}
s_responseQueueMutex.unlock();
_responseQueueMutex.unlock();
if (response)
{
@ -968,6 +986,66 @@ void HttpClient::dispatchResponseCallbacks()
}
}
void HttpClient::increaseThreadCount()
{
_threadCountMutex.lock();
++_threadCount;
_threadCountMutex.unlock();
}
void HttpClient::decreaseThreadCountAndMayDeleteThis()
{
bool needDeleteThis = false;
_threadCountMutex.lock();
--_threadCount;
if (0 == _threadCount)
{
needDeleteThis = true;
}
_threadCountMutex.unlock();
if (needDeleteThis)
{
delete this;
}
}
void HttpClient::setTimeoutForConnect(int value)
{
std::lock_guard<std::mutex> lock(_timeoutForConnectMutex);
_timeoutForConnect = value;
}
int HttpClient::getTimeoutForConnect()
{
std::lock_guard<std::mutex> lock(_timeoutForConnectMutex);
return _timeoutForConnect;
}
void HttpClient::setTimeoutForRead(int value)
{
std::lock_guard<std::mutex> lock(_timeoutForReadMutex);
_timeoutForRead = value;
}
int HttpClient::getTimeoutForRead()
{
std::lock_guard<std::mutex> lock(_timeoutForReadMutex);
return _timeoutForRead;
}
const std::string& HttpClient::getCookieFilename()
{
std::lock_guard<std::mutex> lock(_cookieFileMutex);
return _cookieFilename;
}
const std::string& HttpClient::getSSLVerification()
{
std::lock_guard<std::mutex> lock(_sslCaFileMutex);
return _sslCaFilename;
}
}
NS_CC_END

View File

@ -26,56 +26,26 @@
#include "HttpClient.h"
#include <thread>
#include <queue>
#include <condition_variable>
#include <errno.h>
#import "HttpAsynConnection.h"
#include "HttpCookie.h"
#include "base/CCVector.h"
#import "network/HttpAsynConnection.h"
#include "network/HttpCookie.h"
#include "base/CCDirector.h"
#include "base/CCScheduler.h"
#include "platform/CCFileUtils.h"
NS_CC_BEGIN
namespace network {
static std::mutex s_requestQueueMutex;
static std::mutex s_responseQueueMutex;
static HttpClient *_httpClient = nullptr; // pointer to singleton
static std::condition_variable_any s_SleepCondition;
static Vector<HttpRequest*>* s_requestQueue = nullptr;
static Vector<HttpResponse*>* s_responseQueue = nullptr;
static HttpClient *s_HttpClient = nullptr; // pointer to singleton
static HttpCookie *s_cookie = nullptr;
static const int ERROR_SIZE = 256;
static char s_errorBuffer[ERROR_SIZE] = {0};
static std::string s_cookieFilename = "";
static std::string s_sslCaFilename = "";
static int processTask(HttpRequest *request, NSString *requestType, void *stream, long *errorCode, void *headerStream, char *errorBuffer);
static void processResponse(HttpResponse* response, char* errorBuffer);
static HttpRequest *s_requestSentinel = new HttpRequest;
static int processTask(HttpClient* client, HttpRequest *request, NSString *requestType, void *stream, long *errorCode, void *headerStream, char *errorBuffer);
// Worker thread
void HttpClient::networkThread()
{
auto scheduler = Director::getInstance()->getScheduler();
increaseThreadCount();
while (true) @autoreleasepool {
@ -83,77 +53,90 @@ void HttpClient::networkThread()
// step 1: send http request if the requestQueue isn't empty
{
std::lock_guard<std::mutex> lock(s_requestQueueMutex);
while (s_requestQueue->empty()) {
s_SleepCondition.wait(s_requestQueueMutex);
std::lock_guard<std::mutex> lock(_requestQueueMutex);
while (_requestQueue.empty()) {
_sleepCondition.wait(_requestQueueMutex);
}
request = s_requestQueue->at(0);
s_requestQueue->erase(0);
request = _requestQueue.at(0);
_requestQueue.erase(0);
}
if (request == s_requestSentinel) {
if (request == _requestSentinel) {
break;
}
// Create a HttpResponse object, the default setting is http access failed
HttpResponse *response = new (std::nothrow) HttpResponse(request);
processResponse(response, s_errorBuffer);
processResponse(response, _responseMessage);
// add response packet into queue
s_responseQueueMutex.lock();
s_responseQueue->pushBack(response);
s_responseQueueMutex.unlock();
_responseQueueMutex.lock();
_responseQueue.pushBack(response);
_responseQueueMutex.unlock();
if (nullptr != s_HttpClient) {
scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this));
_schedulerMutex.lock();
if (nullptr != _scheduler)
{
_scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this));
}
_schedulerMutex.unlock();
}
// cleanup: if worker thread received quit signal, clean up un-completed request queue
s_requestQueueMutex.lock();
s_requestQueue->clear();
s_requestQueueMutex.unlock();
_requestQueueMutex.lock();
_requestQueue.clear();
_requestQueueMutex.unlock();
_responseQueueMutex.lock();
_responseQueue.clear();
_responseQueueMutex.unlock();
if (s_requestQueue != nullptr) {
delete s_requestQueue;
s_requestQueue = nullptr;
delete s_responseQueue;
s_responseQueue = nullptr;
}
decreaseThreadCountAndMayDeleteThis();
}
// Worker thread
void HttpClient::networkThreadAlone(HttpRequest* request, HttpResponse* response)
{
char errorBuffer[ERROR_SIZE] = { 0 };
processResponse(response, errorBuffer);
increaseThreadCount();
auto scheduler = Director::getInstance()->getScheduler();
scheduler->performFunctionInCocosThread([response, request]{
char responseMessage[RESPONSE_BUFFER_SIZE] = { 0 };
processResponse(response, responseMessage);
_schedulerMutex.lock();
if (nullptr != _scheduler)
{
_scheduler->performFunctionInCocosThread([this, response, request]{
const ccHttpRequestCallback& callback = request->getCallback();
Ref* pTarget = request->getTarget();
SEL_HttpResponse pSelector = request->getSelector();
if (callback != nullptr)
{
callback(s_HttpClient, response);
callback(this, response);
}
else if (pTarget && pSelector)
{
(pTarget->*pSelector)(s_HttpClient, response);
(pTarget->*pSelector)(this, response);
}
response->release();
// do not release in other thread
request->release();
});
}
_schedulerMutex.unlock();
decreaseThreadCountAndMayDeleteThis();
}
//Process Request
static int processTask(HttpRequest *request, NSString* requestType, void *stream, long *responseCode, void *headerStream, char *errorBuffer)
static int processTask(HttpClient* client, HttpRequest* request, NSString* requestType, void* stream, long* responseCode, void* headerStream, char* errorBuffer)
{
if (nullptr == client)
{
strcpy(errorBuffer, "client object is invalid");
return 0;
}
//create request with url
NSString* urlstring = [NSString stringWithUTF8String:request->getUrl()];
NSURL *url = [NSURL URLWithString:urlstring];
@ -199,9 +182,10 @@ static int processTask(HttpRequest *request, NSString* requestType, void *stream
}
//read cookie propertities from file and set cookie
if(!s_cookieFilename.empty())
std::string cookieFilename = client->getCookieFilename();
if(!cookieFilename.empty() && nullptr != client->getCookie())
{
const CookiesInfo* cookieInfo = s_cookie->getMatchCookie(request->getUrl());
const CookiesInfo* cookieInfo = client->getCookie()->getMatchCookie(request->getUrl());
if(cookieInfo != nullptr)
{
NSString *domain = [NSString stringWithCString:cookieInfo->domain.c_str() encoding:[NSString defaultCStringEncoding]];
@ -227,12 +211,13 @@ static int processTask(HttpRequest *request, NSString* requestType, void *stream
httpAsynConn.srcURL = urlstring;
httpAsynConn.sslFile = nil;
if(!s_sslCaFilename.empty())
std::string sslCaFileName = client->getSSLVerification();
if(!sslCaFileName.empty())
{
long len = s_sslCaFilename.length();
long pos = s_sslCaFilename.rfind('.', len-1);
long len = sslCaFileName.length();
long pos = sslCaFileName.rfind('.', len-1);
httpAsynConn.sslFile = [NSString stringWithUTF8String:s_sslCaFilename.substr(0, pos-1).c_str()];
httpAsynConn.sslFile = [NSString stringWithUTF8String:sslCaFileName.substr(0, pos-1).c_str()];
}
[httpAsynConn startRequest:nsrequest];
@ -259,7 +244,7 @@ static int processTask(HttpRequest *request, NSString* requestType, void *stream
*responseCode = httpAsynConn.responseCode;
//add cookie to cookies vector
if(!s_cookieFilename.empty())
if(!cookieFilename.empty())
{
NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:httpAsynConn.responseHeader forURL:url];
for (NSHTTPCookie *cookie in cookies)
@ -282,7 +267,7 @@ static int processTask(HttpRequest *request, NSString* requestType, void *stream
cookieInfo.value = [value cStringUsingEncoding: NSUTF8StringEncoding];
cookieInfo.tailmatch = true;
s_cookie->updateOrAddCookie(&cookieInfo);
client->getCookie()->updateOrAddCookie(&cookieInfo);
}
}
@ -313,8 +298,193 @@ static int processTask(HttpRequest *request, NSString* requestType, void *stream
return 1;
}
// HttpClient implementation
HttpClient* HttpClient::getInstance()
{
if (_httpClient == nullptr)
{
_httpClient = new (std::nothrow) HttpClient();
}
return _httpClient;
}
void HttpClient::destroyInstance()
{
if (nullptr == _httpClient)
{
CCLOG("HttpClient singleton is nullptr");
return;
}
CCLOG("HttpClient::destroyInstance begin");
auto thiz = _httpClient;
_httpClient = nullptr;
thiz->_scheduler->unscheduleAllForTarget(thiz);
thiz->_schedulerMutex.lock();
thiz->_scheduler = nullptr;
thiz->_schedulerMutex.unlock();
thiz->_requestQueueMutex.lock();
thiz->_requestQueue.pushBack(thiz->_requestSentinel);
thiz->_requestQueueMutex.unlock();
thiz->_sleepCondition.notify_one();
thiz->decreaseThreadCountAndMayDeleteThis();
CCLOG("HttpClient::destroyInstance() finished!");
}
void HttpClient::enableCookies(const char* cookieFile)
{
_cookieFileMutex.lock();
if (cookieFile)
{
_cookieFilename = std::string(cookieFile);
_cookieFilename = FileUtils::getInstance()->fullPathForFilename(_cookieFilename);
}
else
{
_cookieFilename = (FileUtils::getInstance()->getWritablePath() + "cookieFile.txt");
}
_cookieFileMutex.unlock();
if (nullptr == _cookie)
{
_cookie = new(std::nothrow)HttpCookie;
}
_cookie->setCookieFileName(_cookieFilename);
_cookie->readFile();
}
void HttpClient::setSSLVerification(const std::string& caFile)
{
std::lock_guard<std::mutex> lock(_sslCaFileMutex);
_sslCaFilename = caFile;
}
HttpClient::HttpClient()
: _timeoutForConnect(30)
, _timeoutForRead(60)
, _isInited(false)
, _threadCount(0)
, _requestSentinel(new HttpRequest())
, _cookie(nullptr)
{
CCLOG("In the constructor of HttpClient!");
memset(_responseMessage, 0, sizeof(char) * RESPONSE_BUFFER_SIZE);
_scheduler = Director::getInstance()->getScheduler();
increaseThreadCount();
}
HttpClient::~HttpClient()
{
CC_SAFE_DELETE(_requestSentinel);
if (!_cookieFilename.empty() && nullptr != _cookie)
{
_cookie->writeFile();
CC_SAFE_DELETE(_cookie);
}
CCLOG("HttpClient destructor");
}
//Lazy create semaphore & mutex & thread
bool HttpClient::lazyInitThreadSemphore()
{
if (_isInited)
{
return true;
}
else
{
auto t = std::thread(CC_CALLBACK_0(HttpClient::networkThread, this));
t.detach();
_isInited = true;
}
return true;
}
//Add a get task to queue
void HttpClient::send(HttpRequest* request)
{
if (false == lazyInitThreadSemphore())
{
return;
}
if (!request)
{
return;
}
request->retain();
_requestQueueMutex.lock();
_requestQueue.pushBack(request);
_requestQueueMutex.unlock();
// Notify thread start to work
_sleepCondition.notify_one();
}
void HttpClient::sendImmediate(HttpRequest* request)
{
if(!request)
{
return;
}
request->retain();
// Create a HttpResponse object, the default setting is http access failed
HttpResponse *response = new (std::nothrow) HttpResponse(request);
auto t = std::thread(&HttpClient::networkThreadAlone, this, request, response);
t.detach();
}
// Poll and notify main thread if responses exists in queue
void HttpClient::dispatchResponseCallbacks()
{
// log("CCHttpClient::dispatchResponseCallbacks is running");
//occurs when cocos thread fires but the network thread has already quited
HttpResponse* response = nullptr;
_responseQueueMutex.lock();
if (!_responseQueue.empty())
{
response = _responseQueue.at(0);
_responseQueue.erase(0);
}
_responseQueueMutex.unlock();
if (response)
{
HttpRequest *request = response->getHttpRequest();
const ccHttpRequestCallback& callback = request->getCallback();
Ref* pTarget = request->getTarget();
SEL_HttpResponse pSelector = request->getSelector();
if (callback != nullptr)
{
callback(this, response);
}
else if (pTarget && pSelector)
{
(pTarget->*pSelector)(this, response);
}
response->release();
// do not release in other thread
request->release();
}
}
// Process Response
static void processResponse(HttpResponse* response, char* errorBuffer)
void HttpClient::processResponse(HttpResponse* response, char* responseMessage)
{
auto request = response->getHttpRequest();
long responseCode = -1;
@ -345,12 +515,13 @@ static void processResponse(HttpResponse* response, char* errorBuffer)
break;
}
retValue = processTask(request,
retValue = processTask(this,
request,
requestType,
response->getResponseData(),
&responseCode,
response->getResponseHeader(),
errorBuffer);
responseMessage);
// write data to HttpResponse
response->setResponseCode(responseCode);
@ -362,167 +533,69 @@ static void processResponse(HttpResponse* response, char* errorBuffer)
else
{
response->setSucceed(false);
response->setErrorBuffer(errorBuffer);
response->setErrorBuffer(responseMessage);
}
}
// HttpClient implementation
HttpClient* HttpClient::getInstance()
void HttpClient::increaseThreadCount()
{
if (s_HttpClient == nullptr) {
s_HttpClient = new (std::nothrow) HttpClient();
}
return s_HttpClient;
_threadCountMutex.lock();
++_threadCount;
_threadCountMutex.unlock();
}
void HttpClient::destroyInstance()
void HttpClient::decreaseThreadCountAndMayDeleteThis()
{
CC_SAFE_DELETE(s_HttpClient);
}
void HttpClient::enableCookies(const char* cookieFile) {
if (cookieFile) {
s_cookieFilename = std::string(cookieFile);
s_cookieFilename = FileUtils::getInstance()->fullPathForFilename(s_cookieFilename);
}
else {
s_cookieFilename = (FileUtils::getInstance()->getWritablePath() + "cookieFile.txt");
bool needDeleteThis = false;
_threadCountMutex.lock();
--_threadCount;
if (0 == _threadCount)
{
needDeleteThis = true;
}
s_cookie = new(std::nothrow)HttpCookie;
s_cookie->setCookieFileName(s_cookieFilename);
s_cookie->readFile();
_threadCountMutex.unlock();
if (needDeleteThis)
{
delete this;
}
}
void HttpClient::setSSLVerification(const std::string& caFile)
void HttpClient::setTimeoutForConnect(int value)
{
s_sslCaFilename = caFile;
std::lock_guard<std::mutex> lock(_timeoutForConnectMutex);
_timeoutForConnect = value;
}
HttpClient::HttpClient()
: _timeoutForConnect(30)
, _timeoutForRead(60)
int HttpClient::getTimeoutForConnect()
{
std::lock_guard<std::mutex> lock(_timeoutForConnectMutex);
return _timeoutForConnect;
}
HttpClient::~HttpClient()
void HttpClient::setTimeoutForRead(int value)
{
if (s_requestQueue != nullptr) {
{
std::lock_guard<std::mutex> lock(s_requestQueueMutex);
s_requestQueue->pushBack(s_requestSentinel);
}
s_SleepCondition.notify_one();
}
s_HttpClient = nullptr;
if(!s_cookieFilename.empty())
{
s_cookie->writeFile();
//delete s_cookie;
}
//s_cookie = nullptr;
std::lock_guard<std::mutex> lock(_timeoutForReadMutex);
_timeoutForRead = value;
}
//Lazy create semaphore & mutex & thread
bool HttpClient::lazyInitThreadSemphore()
int HttpClient::getTimeoutForRead()
{
if (s_requestQueue != nullptr) {
return true;
} else {
s_requestQueue = new (std::nothrow) Vector<HttpRequest*>();
s_responseQueue = new (std::nothrow) Vector<HttpResponse*>();
auto t = std::thread(CC_CALLBACK_0(HttpClient::networkThread, this));
t.detach();
}
return true;
std::lock_guard<std::mutex> lock(_timeoutForReadMutex);
return _timeoutForRead;
}
//Add a get task to queue
void HttpClient::send(HttpRequest* request)
const std::string& HttpClient::getCookieFilename()
{
if (false == lazyInitThreadSemphore())
{
return;
}
if (!request)
{
return;
}
request->retain();
if (nullptr != s_requestQueue) {
s_requestQueueMutex.lock();
s_requestQueue->pushBack(request);
s_requestQueueMutex.unlock();
// Notify thread start to work
s_SleepCondition.notify_one();
}
std::lock_guard<std::mutex> lock(_cookieFileMutex);
return _cookieFilename;
}
void HttpClient::sendImmediate(HttpRequest* request)
const std::string& HttpClient::getSSLVerification()
{
if(!request)
{
return;
}
request->retain();
// Create a HttpResponse object, the default setting is http access failed
HttpResponse *response = new (std::nothrow) HttpResponse(request);
auto t = std::thread(&HttpClient::networkThreadAlone, this, request, response);
t.detach();
}
// Poll and notify main thread if responses exists in queue
void HttpClient::dispatchResponseCallbacks()
{
// log("CCHttpClient::dispatchResponseCallbacks is running");
//occurs when cocos thread fires but the network thread has already quited
if (nullptr == s_responseQueue) {
return;
}
HttpResponse* response = nullptr;
s_responseQueueMutex.lock();
if (!s_responseQueue->empty())
{
response = s_responseQueue->at(0);
s_responseQueue->erase(0);
}
s_responseQueueMutex.unlock();
if (response)
{
HttpRequest *request = response->getHttpRequest();
const ccHttpRequestCallback& callback = request->getCallback();
Ref* pTarget = request->getTarget();
SEL_HttpResponse pSelector = request->getSelector();
if (callback != nullptr)
{
callback(this, response);
}
else if (pTarget && pSelector)
{
(pTarget->*pSelector)(this, response);
}
response->release();
// do not release in other thread
request->release();
}
std::lock_guard<std::mutex> lock(_sslCaFileMutex);
return _sslCaFilename;
}
}

View File

@ -25,48 +25,24 @@
****************************************************************************/
#include "HttpClient.h"
#include <thread>
#include <queue>
#include <condition_variable>
#include <errno.h>
#include <curl/curl.h>
#include "base/CCVector.h"
#include "base/CCDirector.h"
#include "base/CCScheduler.h"
#include "platform/CCFileUtils.h"
NS_CC_BEGIN
namespace network {
static std::mutex s_requestQueueMutex;
static std::mutex s_responseQueueMutex;
static std::condition_variable_any s_SleepCondition;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
typedef int int32_t;
#endif
static Vector<HttpRequest*>* s_requestQueue = nullptr;
static Vector<HttpResponse*>* s_responseQueue = nullptr;
static HttpClient *s_pHttpClient = nullptr; // pointer to singleton
static char s_errorBuffer[CURL_ERROR_SIZE] = {0};
static HttpClient* _httpClient = nullptr; // pointer to singleton
typedef size_t (*write_callback)(void *ptr, size_t size, size_t nmemb, void *stream);
static std::string s_cookieFilename = "";
static std::string s_sslCaFilename = "";
// Callback function used by libcurl for collect response data
static size_t writeData(void *ptr, size_t size, size_t nmemb, void *stream)
{
@ -94,19 +70,16 @@ static size_t writeHeaderData(void *ptr, size_t size, size_t nmemb, void *stream
}
static int processGetTask(HttpRequest *request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char *errorBuffer);
static int processPostTask(HttpRequest *request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char *errorBuffer);
static int processPutTask(HttpRequest *request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char *errorBuffer);
static int processDeleteTask(HttpRequest *request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char *errorBuffer);
static int processGetTask(HttpClient* client, HttpRequest* request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char* errorBuffer);
static int processPostTask(HttpClient* client, HttpRequest* request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char* errorBuffer);
static int processPutTask(HttpClient* client, HttpRequest* request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char* errorBuffer);
static int processDeleteTask(HttpClient* client, HttpRequest* request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char* errorBuffer);
// int processDownloadTask(HttpRequest *task, write_callback callback, void *stream, int32_t *errorCode);
static void processResponse(HttpResponse* response, char* errorBuffer);
static HttpRequest *s_requestSentinel = new HttpRequest;
// Worker thread
void HttpClient::networkThread()
{
auto scheduler = Director::getInstance()->getScheduler();
increaseThreadCount();
while (true)
{
@ -114,15 +87,16 @@ void HttpClient::networkThread()
// step 1: send http request if the requestQueue isn't empty
{
std::lock_guard<std::mutex> lock(s_requestQueueMutex);
while (s_requestQueue->empty()) {
s_SleepCondition.wait(s_requestQueueMutex);
std::lock_guard<std::mutex> lock(_requestQueueMutex);
while (_requestQueue.empty())
{
_sleepCondition.wait(_requestQueueMutex);
}
request = s_requestQueue->at(0);
s_requestQueue->erase(0);
request = _requestQueue.at(0);
_requestQueue.erase(0);
}
if (request == s_requestSentinel) {
if (request == _requestSentinel) {
break;
}
@ -131,62 +105,70 @@ void HttpClient::networkThread()
// Create a HttpResponse object, the default setting is http access failed
HttpResponse *response = new (std::nothrow) HttpResponse(request);
processResponse(response, s_errorBuffer);
processResponse(response, _responseMessage);
// add response packet into queue
s_responseQueueMutex.lock();
s_responseQueue->pushBack(response);
s_responseQueueMutex.unlock();
_responseQueueMutex.lock();
_responseQueue.pushBack(response);
_responseQueueMutex.unlock();
if (nullptr != s_pHttpClient) {
scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this));
_schedulerMutex.lock();
if (nullptr != _scheduler)
{
_scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this));
}
_schedulerMutex.unlock();
}
// cleanup: if worker thread received quit signal, clean up un-completed request queue
s_requestQueueMutex.lock();
s_requestQueue->clear();
s_requestQueueMutex.unlock();
_requestQueueMutex.lock();
_requestQueue.clear();
_requestQueueMutex.unlock();
_responseQueueMutex.lock();
_responseQueue.clear();
_responseQueueMutex.unlock();
if (s_requestQueue != nullptr) {
delete s_requestQueue;
s_requestQueue = nullptr;
delete s_responseQueue;
s_responseQueue = nullptr;
}
decreaseThreadCountAndMayDeleteThis();
}
// Worker thread
void HttpClient::networkThreadAlone(HttpRequest* request, HttpResponse* response)
{
char errorBuffer[CURL_ERROR_SIZE] = { 0 };
processResponse(response, errorBuffer);
increaseThreadCount();
auto scheduler = Director::getInstance()->getScheduler();
scheduler->performFunctionInCocosThread([response, request]{
char responseMessage[RESPONSE_BUFFER_SIZE] = { 0 };
processResponse(response, responseMessage);
_schedulerMutex.lock();
if (nullptr != _scheduler)
{
_scheduler->performFunctionInCocosThread([this, response, request]{
const ccHttpRequestCallback& callback = request->getCallback();
Ref* pTarget = request->getTarget();
SEL_HttpResponse pSelector = request->getSelector();
if (callback != nullptr)
{
callback(s_pHttpClient, response);
callback(this, response);
}
else if (pTarget && pSelector)
{
(pTarget->*pSelector)(s_pHttpClient, response);
(pTarget->*pSelector)(this, response);
}
response->release();
// do not release in other thread
request->release();
});
}
_schedulerMutex.unlock();
decreaseThreadCountAndMayDeleteThis();
}
//Configure curl's timeout property
static bool configureCURL(CURL *handle, char *errorBuffer)
static bool configureCURL(HttpClient* client, CURL* handle, char* errorBuffer)
{
if (!handle) {
return false;
@ -205,13 +187,15 @@ static bool configureCURL(CURL *handle, char *errorBuffer)
if (code != CURLE_OK) {
return false;
}
if (s_sslCaFilename.empty()) {
std::string sslCaFilename = client->getSSLVerification();
if (sslCaFilename.empty()) {
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L);
} else {
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(handle, CURLOPT_CAINFO, s_sslCaFilename.c_str());
curl_easy_setopt(handle, CURLOPT_CAINFO, sslCaFilename.c_str());
}
// FIXED #3224: The subthread of CCHttpClient interrupts main thread if timeout comes.
@ -255,11 +239,11 @@ public:
* @param callback Response write callback
* @param stream Response write stream
*/
bool init(HttpRequest *request, write_callback callback, void *stream, write_callback headerCallback, void *headerStream, char *errorBuffer)
bool init(HttpClient* client, HttpRequest* request, write_callback callback, void* stream, write_callback headerCallback, void* headerStream, char* errorBuffer)
{
if (!_curl)
return false;
if (!configureCURL(_curl, errorBuffer))
if (!configureCURL(client, _curl, errorBuffer))
return false;
/* get custom header data (if set) */
@ -273,11 +257,12 @@ public:
if (!setOption(CURLOPT_HTTPHEADER, _headers))
return false;
}
if (!s_cookieFilename.empty()) {
if (!setOption(CURLOPT_COOKIEFILE, s_cookieFilename.c_str())) {
std::string cookieFilename = client->getCookieFilename();
if (!cookieFilename.empty()) {
if (!setOption(CURLOPT_COOKIEFILE, cookieFilename.c_str())) {
return false;
}
if (!setOption(CURLOPT_COOKIEJAR, s_cookieFilename.c_str())) {
if (!setOption(CURLOPT_COOKIEJAR, cookieFilename.c_str())) {
return false;
}
}
@ -307,20 +292,20 @@ public:
};
//Process Get Request
static int processGetTask(HttpRequest *request, write_callback callback, void *stream, long *responseCode, write_callback headerCallback, void *headerStream, char *errorBuffer)
static int processGetTask(HttpClient* client, HttpRequest* request, write_callback callback, void* stream, long* responseCode, write_callback headerCallback, void* headerStream, char* errorBuffer)
{
CURLRaii curl;
bool ok = curl.init(request, callback, stream, headerCallback, headerStream, errorBuffer)
bool ok = curl.init(client, request, callback, stream, headerCallback, headerStream, errorBuffer)
&& curl.setOption(CURLOPT_FOLLOWLOCATION, true)
&& curl.perform(responseCode);
return ok ? 0 : 1;
}
//Process POST Request
static int processPostTask(HttpRequest *request, write_callback callback, void *stream, long *responseCode, write_callback headerCallback, void *headerStream, char *errorBuffer)
static int processPostTask(HttpClient* client, HttpRequest* request, write_callback callback, void* stream, long* responseCode, write_callback headerCallback, void* headerStream, char* errorBuffer)
{
CURLRaii curl;
bool ok = curl.init(request, callback, stream, headerCallback, headerStream, errorBuffer)
bool ok = curl.init(client, request, callback, stream, headerCallback, headerStream, errorBuffer)
&& curl.setOption(CURLOPT_POST, 1)
&& curl.setOption(CURLOPT_POSTFIELDS, request->getRequestData())
&& curl.setOption(CURLOPT_POSTFIELDSIZE, request->getRequestDataSize())
@ -329,10 +314,10 @@ static int processPostTask(HttpRequest *request, write_callback callback, void *
}
//Process PUT Request
static int processPutTask(HttpRequest *request, write_callback callback, void *stream, long *responseCode, write_callback headerCallback, void *headerStream, char *errorBuffer)
static int processPutTask(HttpClient* client, HttpRequest* request, write_callback callback, void* stream, long* responseCode, write_callback headerCallback, void* headerStream, char* errorBuffer)
{
CURLRaii curl;
bool ok = curl.init(request, callback, stream, headerCallback, headerStream, errorBuffer)
bool ok = curl.init(client, request, callback, stream, headerCallback, headerStream, errorBuffer)
&& curl.setOption(CURLOPT_CUSTOMREQUEST, "PUT")
&& curl.setOption(CURLOPT_POSTFIELDS, request->getRequestData())
&& curl.setOption(CURLOPT_POSTFIELDSIZE, request->getRequestDataSize())
@ -341,146 +326,105 @@ static int processPutTask(HttpRequest *request, write_callback callback, void *s
}
//Process DELETE Request
static int processDeleteTask(HttpRequest *request, write_callback callback, void *stream, long *responseCode, write_callback headerCallback, void *headerStream, char *errorBuffer)
static int processDeleteTask(HttpClient* client, HttpRequest* request, write_callback callback, void* stream, long* responseCode, write_callback headerCallback, void* headerStream, char* errorBuffer)
{
CURLRaii curl;
bool ok = curl.init(request, callback, stream, headerCallback, headerStream, errorBuffer)
bool ok = curl.init(client, request, callback, stream, headerCallback, headerStream, errorBuffer)
&& curl.setOption(CURLOPT_CUSTOMREQUEST, "DELETE")
&& curl.setOption(CURLOPT_FOLLOWLOCATION, true)
&& curl.perform(responseCode);
return ok ? 0 : 1;
}
// Process Response
static void processResponse(HttpResponse* response, char* errorBuffer)
{
auto request = response->getHttpRequest();
long responseCode = -1;
int retValue = 0;
// Process the request -> get response packet
switch (request->getRequestType())
{
case HttpRequest::Type::GET: // HTTP GET
retValue = processGetTask(request,
writeData,
response->getResponseData(),
&responseCode,
writeHeaderData,
response->getResponseHeader(),
errorBuffer);
break;
case HttpRequest::Type::POST: // HTTP POST
retValue = processPostTask(request,
writeData,
response->getResponseData(),
&responseCode,
writeHeaderData,
response->getResponseHeader(),
errorBuffer);
break;
case HttpRequest::Type::PUT:
retValue = processPutTask(request,
writeData,
response->getResponseData(),
&responseCode,
writeHeaderData,
response->getResponseHeader(),
errorBuffer);
break;
case HttpRequest::Type::DELETE:
retValue = processDeleteTask(request,
writeData,
response->getResponseData(),
&responseCode,
writeHeaderData,
response->getResponseHeader(),
errorBuffer);
break;
default:
CCASSERT(true, "CCHttpClient: unknown request type, only GET and POSt are supported");
break;
}
// write data to HttpResponse
response->setResponseCode(responseCode);
if (retValue != 0)
{
response->setSucceed(false);
response->setErrorBuffer(errorBuffer);
}
else
{
response->setSucceed(true);
}
}
// HttpClient implementation
HttpClient* HttpClient::getInstance()
{
if (s_pHttpClient == nullptr) {
s_pHttpClient = new (std::nothrow) HttpClient();
if (_httpClient == nullptr)
{
_httpClient = new (std::nothrow) HttpClient();
}
return s_pHttpClient;
return _httpClient;
}
void HttpClient::destroyInstance()
{
CC_SAFE_DELETE(s_pHttpClient);
if (nullptr == _httpClient)
{
CCLOG("HttpClient singleton is nullptr");
return;
}
CCLOG("HttpClient::destroyInstance begin");
auto thiz = _httpClient;
_httpClient = nullptr;
thiz->_scheduler->unscheduleAllForTarget(thiz);
thiz->_schedulerMutex.lock();
thiz->_scheduler = nullptr;
thiz->_schedulerMutex.unlock();
thiz->_requestQueueMutex.lock();
thiz->_requestQueue.pushBack(thiz->_requestSentinel);
thiz->_requestQueueMutex.unlock();
thiz->_sleepCondition.notify_one();
thiz->decreaseThreadCountAndMayDeleteThis();
CCLOG("HttpClient::destroyInstance() finished!");
}
void HttpClient::enableCookies(const char* cookieFile) {
if (cookieFile) {
s_cookieFilename = std::string(cookieFile);
void HttpClient::enableCookies(const char* cookieFile)
{
std::lock_guard<std::mutex> lock(_cookieFileMutex);
if (cookieFile)
{
_cookieFilename = std::string(cookieFile);
}
else {
s_cookieFilename = (FileUtils::getInstance()->getWritablePath() + "cookieFile.txt");
else
{
_cookieFilename = (FileUtils::getInstance()->getWritablePath() + "cookieFile.txt");
}
}
void HttpClient::setSSLVerification(const std::string& caFile)
{
s_sslCaFilename = caFile;
std::lock_guard<std::mutex> lock(_sslCaFileMutex);
_sslCaFilename = caFile;
}
HttpClient::HttpClient()
: _timeoutForConnect(30)
, _timeoutForRead(60)
, _isInited(false)
, _threadCount(0)
, _requestSentinel(new HttpRequest())
, _cookie(nullptr)
{
CCLOG("In the constructor of HttpClient!");
memset(_responseMessage, 0, RESPONSE_BUFFER_SIZE * sizeof(char));
_scheduler = Director::getInstance()->getScheduler();
increaseThreadCount();
}
HttpClient::~HttpClient()
{
if (s_requestQueue != nullptr) {
{
std::lock_guard<std::mutex> lock(s_requestQueueMutex);
s_requestQueue->pushBack(s_requestSentinel);
}
s_SleepCondition.notify_one();
}
s_pHttpClient = nullptr;
CC_SAFE_DELETE(_requestSentinel);
CCLOG("HttpClient destructor");
}
//Lazy create semaphore & mutex & thread
bool HttpClient::lazyInitThreadSemphore()
{
if (s_requestQueue != nullptr) {
if (_isInited)
{
return true;
} else {
s_requestQueue = new (std::nothrow) Vector<HttpRequest*>();
s_responseQueue = new (std::nothrow) Vector<HttpResponse*>();
}
else
{
auto t = std::thread(CC_CALLBACK_0(HttpClient::networkThread, this));
t.detach();
_isInited = true;
}
return true;
@ -501,14 +445,12 @@ void HttpClient::send(HttpRequest* request)
request->retain();
if (nullptr != s_requestQueue) {
s_requestQueueMutex.lock();
s_requestQueue->pushBack(request);
s_requestQueueMutex.unlock();
_requestQueueMutex.lock();
_requestQueue.pushBack(request);
_requestQueueMutex.unlock();
// Notify thread start to work
s_SleepCondition.notify_one();
}
_sleepCondition.notify_one();
}
void HttpClient::sendImmediate(HttpRequest* request)
@ -531,20 +473,15 @@ void HttpClient::dispatchResponseCallbacks()
{
// log("CCHttpClient::dispatchResponseCallbacks is running");
//occurs when cocos thread fires but the network thread has already quited
if (nullptr == s_responseQueue) {
return;
}
HttpResponse* response = nullptr;
s_responseQueueMutex.lock();
if (!s_responseQueue->empty())
_responseQueueMutex.lock();
if (!_responseQueue.empty())
{
response = s_responseQueue->at(0);
s_responseQueue->erase(0);
response = _responseQueue.at(0);
_responseQueue.erase(0);
}
s_responseQueueMutex.unlock();
_responseQueueMutex.unlock();
if (response)
{
@ -568,6 +505,134 @@ void HttpClient::dispatchResponseCallbacks()
}
}
// Process Response
void HttpClient::processResponse(HttpResponse* response, char* responseMessage)
{
auto request = response->getHttpRequest();
long responseCode = -1;
int retValue = 0;
// Process the request -> get response packet
switch (request->getRequestType())
{
case HttpRequest::Type::GET: // HTTP GET
retValue = processGetTask(this, request,
writeData,
response->getResponseData(),
&responseCode,
writeHeaderData,
response->getResponseHeader(),
responseMessage);
break;
case HttpRequest::Type::POST: // HTTP POST
retValue = processPostTask(this, request,
writeData,
response->getResponseData(),
&responseCode,
writeHeaderData,
response->getResponseHeader(),
responseMessage);
break;
case HttpRequest::Type::PUT:
retValue = processPutTask(this, request,
writeData,
response->getResponseData(),
&responseCode,
writeHeaderData,
response->getResponseHeader(),
responseMessage);
break;
case HttpRequest::Type::DELETE:
retValue = processDeleteTask(this, request,
writeData,
response->getResponseData(),
&responseCode,
writeHeaderData,
response->getResponseHeader(),
responseMessage);
break;
default:
CCASSERT(true, "CCHttpClient: unknown request type, only GET and POSt are supported");
break;
}
// write data to HttpResponse
response->setResponseCode(responseCode);
if (retValue != 0)
{
response->setSucceed(false);
response->setErrorBuffer(responseMessage);
}
else
{
response->setSucceed(true);
}
}
void HttpClient::increaseThreadCount()
{
_threadCountMutex.lock();
++_threadCount;
_threadCountMutex.unlock();
}
void HttpClient::decreaseThreadCountAndMayDeleteThis()
{
bool needDeleteThis = false;
_threadCountMutex.lock();
--_threadCount;
if (0 == _threadCount)
{
needDeleteThis = true;
}
_threadCountMutex.unlock();
if (needDeleteThis)
{
delete this;
}
}
void HttpClient::setTimeoutForConnect(int value)
{
std::lock_guard<std::mutex> lock(_timeoutForConnectMutex);
_timeoutForConnect = value;
}
int HttpClient::getTimeoutForConnect()
{
std::lock_guard<std::mutex> lock(_timeoutForConnectMutex);
return _timeoutForConnect;
}
void HttpClient::setTimeoutForRead(int value)
{
std::lock_guard<std::mutex> lock(_timeoutForReadMutex);
_timeoutForRead = value;
}
int HttpClient::getTimeoutForRead()
{
std::lock_guard<std::mutex> lock(_timeoutForReadMutex);
return _timeoutForRead;
}
const std::string& HttpClient::getCookieFilename()
{
std::lock_guard<std::mutex> lock(_cookieFileMutex);
return _cookieFilename;
}
const std::string& HttpClient::getSSLVerification()
{
std::lock_guard<std::mutex> lock(_sslCaFileMutex);
return _sslCaFilename;
}
}
NS_CC_END

View File

@ -27,8 +27,13 @@
#ifndef __CCHTTPCLIENT_H__
#define __CCHTTPCLIENT_H__
#include <thread>
#include <condition_variable>
#include "base/CCVector.h"
#include "base/CCScheduler.h"
#include "network/HttpRequest.h"
#include "network/HttpResponse.h"
#include "network/HttpCookie.h"
/**
* @addtogroup core
@ -39,6 +44,8 @@ NS_CC_BEGIN
namespace network {
/** Singleton that handles asynchrounous http requests.
*
* Once the request completed, a callback will issued in main thread when it provided during make request.
@ -48,6 +55,11 @@ namespace network {
class CC_DLL HttpClient
{
public:
/**
* The buffer size of _responseMessage
*/
static const int RESPONSE_BUFFER_SIZE = 256;
/**
* Get instance of HttpClient.
*
@ -67,6 +79,13 @@ public:
*/
void enableCookies(const char* cookieFile);
/**
* Get the cookie filename
*
* @return the cookie filename
*/
const std::string& getCookieFilename();
/**
* Set root certificate path for SSL verification.
*
@ -74,6 +93,13 @@ public:
*/
void setSSLVerification(const std::string& caFile);
/**
* Get ths ssl CA filename
*
* @return the ssl CA filename
*/
const std::string& getSSLVerification();
/**
* Add a get request to task queue
*
@ -90,37 +116,39 @@ public:
*/
void sendImmediate(HttpRequest* request);
/**
* Set the timeout value for connecting.
*
* @param value the timeout value for connecting.
*/
inline void setTimeoutForConnect(int value) {_timeoutForConnect = value;};
void setTimeoutForConnect(int value);
/**
* Get the timeout value for connecting.
*
* @return int the timeout value for connecting.
*/
inline int getTimeoutForConnect() {return _timeoutForConnect;}
int getTimeoutForConnect();
/**
* Set the timeout value for reading.
*
* @param value the timeout value for reading.
*/
inline void setTimeoutForRead(int value) {_timeoutForRead = value;};
void setTimeoutForRead(int value);
/**
* Get the timeout value for reading.
*
* @return int the timeout value for reading.
*/
inline int getTimeoutForRead() {return _timeoutForRead;};
int getTimeoutForRead();
HttpCookie* getCookie() const {return _cookie; }
std::mutex& getCookieFileMutex() {return _cookieFileMutex;}
std::mutex& getSSLCaFileMutex() {return _sslCaFileMutex;}
private:
HttpClient();
virtual ~HttpClient();
@ -136,9 +164,44 @@ private:
/** Poll function called from main thread to dispatch callbacks when http requests finished **/
void dispatchResponseCallbacks();
void processResponse(HttpResponse* response, char* responseMessage);
void increaseThreadCount();
void decreaseThreadCountAndMayDeleteThis();
private:
bool _isInited;
int _timeoutForConnect;
std::mutex _timeoutForConnectMutex;
int _timeoutForRead;
std::mutex _timeoutForReadMutex;
int _threadCount;
std::mutex _threadCountMutex;
Scheduler* _scheduler;
std::mutex _schedulerMutex;
Vector<HttpRequest*> _requestQueue;
std::mutex _requestQueueMutex;
Vector<HttpResponse*> _responseQueue;
std::mutex _responseQueueMutex;
std::string _cookieFilename;
std::mutex _cookieFileMutex;
std::string _sslCaFilename;
std::mutex _sslCaFileMutex;
HttpCookie* _cookie;
std::condition_variable_any _sleepCondition;
char _responseMessage[RESPONSE_BUFFER_SIZE];
HttpRequest* _requestSentinel;
};
}
@ -148,4 +211,4 @@ NS_CC_END
// end group
/// @}
#endif //__CCHTTPREQUEST_H__
#endif //__CCHTTPCLIENT_H__

View File

@ -941,23 +941,6 @@ std::string FileUtils::getFullPathForDirectoryAndFilename(const std::string& dir
return ret;
}
std::string FileUtils::searchFullPathForFilename(const std::string& filename) const
{
if (isAbsolutePath(filename))
{
return filename;
}
std::string path = fullPathForFilename(filename);
if (0 == path.compare(filename))
{
return "";
}
else
{
return path;
}
}
bool FileUtils::isFileExist(const std::string& filename) const
{
if (isAbsolutePath(filename))
@ -966,7 +949,7 @@ bool FileUtils::isFileExist(const std::string& filename) const
}
else
{
std::string fullpath = searchFullPathForFilename(filename);
std::string fullpath = fullPathForFilename(filename);
if (fullpath.empty())
return false;
else
@ -1327,7 +1310,7 @@ long FileUtils::getFileSize(const std::string &filepath)
std::string fullpath = filepath;
if (!isAbsolutePath(filepath))
{
fullpath = searchFullPathForFilename(filepath);
fullpath = fullPathForFilename(filepath);
if (fullpath.empty())
return 0;
}

View File

@ -478,16 +478,6 @@ protected:
*/
virtual std::string getFullPathForDirectoryAndFilename(const std::string& directory, const std::string& filename) const;
/**
* Returns the fullpath for a given filename.
* This is an alternative for fullPathForFilename
* It returns empty string instead of the original filename when no file found for the given name.
* @param filename The file name to look up for
* @return The full path for the file, if not found, the return value will be an empty string
*/
virtual std::string searchFullPathForFilename(const std::string& filename) const;
/** Dictionary used to lookup filenames based on a key.
* It is used internally by the following methods:
*

View File

@ -0,0 +1,7 @@
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.cocos2dx.lib">
<application android:allowBackup="true">
</application>
</manifest>

View File

@ -0,0 +1,29 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 10
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
sourceSets.main {
java.srcDirs = ['../java/src','../ControllerManualAdapter/src']
manifest.srcFile "AndroidManifest.xml"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: '../ControllerManualAdapter/libs', include: ['*.jar'])
}

View File

@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in E:\developSoftware\Android\SDK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -0,0 +1,7 @@
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.cocos2dx.lib">
<application android:allowBackup="true" android:label="libcocos2dx">
</application>
</manifest>

View File

@ -0,0 +1,29 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 10
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
sourceSets.main {
java.srcDir "../java/src"
manifest.srcFile "AndroidManifest.xml"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}

View File

@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in E:\developSoftware\Android\SDK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -60,6 +60,20 @@ THE SOFTWARE.
#endif
#endif
#if _MSC_VER > 1800
#pragma comment(lib,"libpng-2015.lib")
#pragma comment(lib,"libjpeg-2015.lib")
#pragma comment(lib,"libtiff-2015.lib")
#pragma comment(lib,"glfw3-2015.lib")
#pragma comment(lib,"libchipmunk-2015.lib")
#else
#pragma comment(lib,"libpng.lib")
#pragma comment(lib,"libjpeg.lib")
#pragma comment(lib,"libtiff.lib")
#pragma comment(lib,"glfw3.lib")
#pragma comment(lib,"libchipmunk.lib")
#endif
#endif //s CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
#endif /* __CCPLATFORMDEFINE_H__*/

View File

@ -134,7 +134,10 @@ bool CCFileUtilsWinRT::isAbsolutePath(const std::string& strPath) const
static Data getData(const std::string& filename, bool forString)
{
if (filename.empty())
{
CCASSERT(!filename.empty(), "Invalid filename!");
}
Data ret;
unsigned char* buffer = nullptr;

View File

@ -104,6 +104,7 @@ Platform::String^ PlatformStringFromString(const std::string& s)
return ref new Platform::String(ws.data(), ws.length());
}
#if 0
// Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
float ConvertDipsToPixels(float dips)
{
@ -115,7 +116,7 @@ float getScaledDPIValue(float v) {
auto dipFactor = DisplayProperties::LogicalDpi / 96.0f;
return v * dipFactor;
}
#endif
void CC_DLL CCLogIPAddresses()
{

Some files were not shown because too many files have changed in this diff Show More