diff --git a/AUTHORS b/AUTHORS index 10cfacd141..135b64cca9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -997,6 +997,9 @@ Developers: jagd Added setSubsteps() and getSubsteps() in PhysicsWorld + + denpen + Fixed a bug that scroll view hidden picks up the touch events. Retired Core Developers: WenSheng Yang diff --git a/CHANGELOG b/CHANGELOG index d64df950a5..84aed66e37 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ cocos2d-x-3.3?? ?? [NEW] ActionManager: added removeAllActionsByTag() + [NEW] Audio: added new audio system for iOS and Android [NEW] GLViewProtocol: added getAllTouches() [NEW] Node: added stopAllActionsByTag() [NEW] PhysicsWorld: add setSubsteps() and getSubsteps() @@ -13,6 +14,7 @@ cocos2d-x-3.3?? ?? [FIX] Node: create unneeded temple `Vec2` object in `setPosition(int, int)`, `setPositionX()` and `setPositionY()` [FIX] Node: skew effect is wrong [FIX] Node: setNormalizedPosition can not take effect if parent position is not changed + [FIX] External: ScrollView: scroll view hidden picks up the touch events [FIX] TextureAtlas: may crash if only drawing part of it cocos2d-x-3.3alpha0 Aug.28 2014 diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fcc2753a1..9656ef3768 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ # ****************************************************************************/ cmake_minimum_required(VERSION 2.8) -project (Cocos2dx) +project (Cocos2d-X) # The version number set(COCOS2D_X_VERSION 3.3.0) @@ -43,6 +43,7 @@ endif(DEBUG_MODE) set(CMAKE_C_FLAGS_DEBUG "-DCOCOS2D_DEBUG=1") set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG}) +# Compiler options if(MSVC) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS -wd4251 -wd4244 -wd4334 -wd4005 -wd4820 -wd4710 @@ -52,8 +53,12 @@ else() set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-exceptions -std=c99") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -std=c++11 -Wno-deprecated-declarations -Wno-reorder") + if(CLANG) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + endif() endif(MSVC) +# Some macro definitions if(WINDOWS) ADD_DEFINITIONS (-D_USRDLL -DCOCOS2DXWIN32_EXPORTS -D_WINDOWS -DWIN32) set(PLATFORM_FOLDER win32) diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj b/build/cocos2d_libs.xcodeproj/project.pbxproj index a518e62b73..eb33637bf1 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj @@ -1267,6 +1267,14 @@ 299CF1FC19A434BC00C378C1 /* ccRandom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 299CF1F919A434BC00C378C1 /* ccRandom.cpp */; }; 299CF1FD19A434BC00C378C1 /* ccRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 299CF1FA19A434BC00C378C1 /* ccRandom.h */; }; 299CF1FE19A434BC00C378C1 /* ccRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 299CF1FA19A434BC00C378C1 /* ccRandom.h */; }; + 3E2BDADE19C030ED0055CDCD /* AudioEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E2BDADD19C030ED0055CDCD /* AudioEngine.h */; }; + 3E2BDAE519C0329B0055CDCD /* AudioCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E2BDADF19C0329B0055CDCD /* AudioCache.h */; }; + 3E2BDAE619C0329B0055CDCD /* AudioCache.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3E2BDAE019C0329B0055CDCD /* AudioCache.mm */; }; + 3E2BDAE719C0329B0055CDCD /* AudioEngine-inl.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E2BDAE119C0329B0055CDCD /* AudioEngine-inl.h */; }; + 3E2BDAE819C0329B0055CDCD /* AudioEngine-inl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3E2BDAE219C0329B0055CDCD /* AudioEngine-inl.mm */; }; + 3E2BDAE919C0329B0055CDCD /* AudioPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E2BDAE319C0329B0055CDCD /* AudioPlayer.h */; }; + 3E2BDAEA19C0329B0055CDCD /* AudioPlayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3E2BDAE419C0329B0055CDCD /* AudioPlayer.mm */; }; + 3E2BDAEC19C0436F0055CDCD /* AudioEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3E2BDAEB19C0436F0055CDCD /* AudioEngine.cpp */; }; 3E6176681960F89B00DE83F5 /* CCController-iOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3E6176551960F89B00DE83F5 /* CCController-iOS.mm */; }; 3E6176691960F89B00DE83F5 /* CCController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E6176561960F89B00DE83F5 /* CCController.h */; }; 3E6176741960F89B00DE83F5 /* CCEventController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3E6176611960F89B00DE83F5 /* CCEventController.cpp */; }; @@ -1791,6 +1799,10 @@ B37510841823ACA100B3BA6A /* CCPhysicsShapeInfo_chipmunk.h in Headers */ = {isa = PBXBuildFile; fileRef = B375104D1823AC7B00B3BA6A /* CCPhysicsShapeInfo_chipmunk.h */; }; B37510851823ACA100B3BA6A /* CCPhysicsWorldInfo_chipmunk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B375104E1823AC7B00B3BA6A /* CCPhysicsWorldInfo_chipmunk.cpp */; }; B37510861823ACA100B3BA6A /* CCPhysicsWorldInfo_chipmunk.h in Headers */ = {isa = PBXBuildFile; fileRef = B375104F1823AC7B00B3BA6A /* CCPhysicsWorldInfo_chipmunk.h */; }; + B60C5BD419AC68B10056FBDE /* CCBillBoard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B60C5BD219AC68B10056FBDE /* CCBillBoard.cpp */; }; + B60C5BD519AC68B10056FBDE /* CCBillBoard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B60C5BD219AC68B10056FBDE /* CCBillBoard.cpp */; }; + B60C5BD619AC68B10056FBDE /* CCBillBoard.h in Headers */ = {isa = PBXBuildFile; fileRef = B60C5BD319AC68B10056FBDE /* CCBillBoard.h */; }; + B60C5BD719AC68B10056FBDE /* CCBillBoard.h in Headers */ = {isa = PBXBuildFile; fileRef = B60C5BD319AC68B10056FBDE /* CCBillBoard.h */; }; ED9C6A9418599AD8000A5232 /* CCNodeGrid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED9C6A9218599AD8000A5232 /* CCNodeGrid.cpp */; }; ED9C6A9518599AD8000A5232 /* CCNodeGrid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED9C6A9218599AD8000A5232 /* CCNodeGrid.cpp */; }; ED9C6A9618599AD8000A5232 /* CCNodeGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = ED9C6A9318599AD8000A5232 /* CCNodeGrid.h */; }; @@ -2278,6 +2290,14 @@ 37936A3C1869B76800E974DD /* reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reader.h; sourceTree = ""; }; 37936A3D1869B76800E974DD /* stringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stringbuffer.h; sourceTree = ""; }; 37936A3E1869B76800E974DD /* writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = writer.h; sourceTree = ""; }; + 3E2BDADD19C030ED0055CDCD /* AudioEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioEngine.h; sourceTree = ""; }; + 3E2BDADF19C0329B0055CDCD /* AudioCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioCache.h; sourceTree = ""; }; + 3E2BDAE019C0329B0055CDCD /* AudioCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AudioCache.mm; sourceTree = ""; }; + 3E2BDAE119C0329B0055CDCD /* AudioEngine-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AudioEngine-inl.h"; sourceTree = ""; }; + 3E2BDAE219C0329B0055CDCD /* AudioEngine-inl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "AudioEngine-inl.mm"; sourceTree = ""; }; + 3E2BDAE319C0329B0055CDCD /* AudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioPlayer.h; sourceTree = ""; }; + 3E2BDAE419C0329B0055CDCD /* AudioPlayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AudioPlayer.mm; sourceTree = ""; }; + 3E2BDAEB19C0436F0055CDCD /* AudioEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioEngine.cpp; sourceTree = ""; }; 3E6176551960F89B00DE83F5 /* CCController-iOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "CCController-iOS.mm"; path = "../base/CCController-iOS.mm"; sourceTree = ""; }; 3E6176561960F89B00DE83F5 /* CCController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCController.h; path = ../base/CCController.h; sourceTree = ""; }; 3E6176611960F89B00DE83F5 /* CCEventController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CCEventController.cpp; path = ../base/CCEventController.cpp; sourceTree = ""; }; @@ -2766,6 +2786,8 @@ B375104F1823AC7B00B3BA6A /* CCPhysicsWorldInfo_chipmunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCPhysicsWorldInfo_chipmunk.h; sourceTree = ""; }; B3AF019E1842FBA400A98B85 /* b2MotorJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2MotorJoint.cpp; sourceTree = ""; }; B3AF019F1842FBA400A98B85 /* b2MotorJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2MotorJoint.h; sourceTree = ""; }; + B60C5BD219AC68B10056FBDE /* CCBillBoard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCBillBoard.cpp; sourceTree = ""; }; + B60C5BD319AC68B10056FBDE /* CCBillBoard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCBillBoard.h; sourceTree = ""; }; ED9C6A9218599AD8000A5232 /* CCNodeGrid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = CCNodeGrid.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; ED9C6A9318599AD8000A5232 /* CCNodeGrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNodeGrid.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -3990,6 +4012,7 @@ 46A15FD01807A56F005B8026 /* audio */ = { isa = PBXGroup; children = ( + 3E2BDAEB19C0436F0055CDCD /* AudioEngine.cpp */, 46A15FE01807A56F005B8026 /* include */, 46A15FE31807A56F005B8026 /* ios */, 46A15FF31807A56F005B8026 /* mac */, @@ -4001,6 +4024,7 @@ 46A15FE01807A56F005B8026 /* include */ = { isa = PBXGroup; children = ( + 3E2BDADD19C030ED0055CDCD /* AudioEngine.h */, 46A15FE11807A56F005B8026 /* Export.h */, 46A15FE21807A56F005B8026 /* SimpleAudioEngine.h */, ); @@ -4010,6 +4034,12 @@ 46A15FE31807A56F005B8026 /* ios */ = { isa = PBXGroup; children = ( + 3E2BDADF19C0329B0055CDCD /* AudioCache.h */, + 3E2BDAE019C0329B0055CDCD /* AudioCache.mm */, + 3E2BDAE119C0329B0055CDCD /* AudioEngine-inl.h */, + 3E2BDAE219C0329B0055CDCD /* AudioEngine-inl.mm */, + 3E2BDAE319C0329B0055CDCD /* AudioPlayer.h */, + 3E2BDAE419C0329B0055CDCD /* AudioPlayer.mm */, 46A15FE41807A56F005B8026 /* CDAudioManager.h */, 46A15FE51807A56F005B8026 /* CDAudioManager.m */, 46A15FE61807A56F005B8026 /* CDConfig.h */, @@ -4703,6 +4733,8 @@ B29594B81926D61F003EEF37 /* 3d */ = { isa = PBXGroup; children = ( + B60C5BD219AC68B10056FBDE /* CCBillBoard.cpp */, + B60C5BD319AC68B10056FBDE /* CCBillBoard.h */, 15AE17E319AAD2F700C27E9E /* 3dExport.h */, 15AE17E419AAD2F700C27E9E /* CCAABB.cpp */, 15AE17E519AAD2F700C27E9E /* CCAABB.h */, @@ -5070,6 +5102,7 @@ 15AE199119AAD37200C27E9E /* ImageViewReader.h in Headers */, 15AE18FE19AAD35000C27E9E /* CCComAttribute.h in Headers */, 50ABBD621925AB0000A911A9 /* Vec4.h in Headers */, + B60C5BD619AC68B10056FBDE /* CCBillBoard.h in Headers */, 15AE1BA419AADFDF00C27E9E /* UILayoutManager.h in Headers */, 1A01C69418F57BE800EFE3A6 /* CCFloat.h in Headers */, 1A57034D180BD09B0088DEC7 /* tinyxml2.h in Headers */, @@ -5368,10 +5401,12 @@ 1A5701A0180BCB590088DEC7 /* CCFont.h in Headers */, 292DB14819B4574100A80320 /* UIEditBoxImpl-ios.h in Headers */, 15AE1A0819AAD3A700C27E9E /* BoneData.h in Headers */, + 3E2BDADE19C030ED0055CDCD /* AudioEngine.h in Headers */, 50ABBD9A1925AB4100A911A9 /* CCGLProgramStateCache.h in Headers */, 15AE181D19AAD2F700C27E9E /* CCBundle3D.h in Headers */, 15AE192519AAD35100C27E9E /* CocoLoader.h in Headers */, 15AE1BBB19AADFF000C27E9E /* HttpRequest.h in Headers */, + B60C5BD719AC68B10056FBDE /* CCBillBoard.h in Headers */, B230ED7419B417AE00364AA8 /* CCTrianglesCommand.h in Headers */, 15AE1A0019AAD3A700C27E9E /* AtlasAttachmentLoader.h in Headers */, 50ED2BE119BEAF7900A0AB90 /* UIEditBoxImpl-win32.h in Headers */, @@ -5420,6 +5455,7 @@ 5034CA22191D591100CE6051 /* ccShader_PositionTextureColorAlphaTest.frag in Headers */, 15AE1B8E19AADA9A00C27E9E /* UIDeprecated.h in Headers */, 15AE1A3919AAD3D500C27E9E /* Box2D.h in Headers */, + 3E2BDAE519C0329B0055CDCD /* AudioCache.h in Headers */, 50ABBECE1925AB6F00A911A9 /* s3tc.h in Headers */, 50643BE519BFCF1800EF68ED /* CCPlatformMacros.h in Headers */, 15AE1BFA19AAE01E00C27E9E /* CCControlSwitch.h in Headers */, @@ -5513,6 +5549,7 @@ 15AE1BAE19AADFDF00C27E9E /* UILayoutParameter.h in Headers */, 15AE18C819AAD33D00C27E9E /* CCMenuItemImageLoader.h in Headers */, 15AE18D119AAD33D00C27E9E /* CCNodeLoaderLibrary.h in Headers */, + 3E2BDAE719C0329B0055CDCD /* AudioEngine-inl.h in Headers */, 15AE1AC319AAD40300C27E9E /* b2DistanceJoint.h in Headers */, 50ABBE741925AB6F00A911A9 /* CCEventListenerMouse.h in Headers */, 1A5702CB180BCE370088DEC7 /* CCTextFieldTTF.h in Headers */, @@ -5546,6 +5583,7 @@ B375107F1823ACA100B3BA6A /* CCPhysicsContactInfo_chipmunk.h in Headers */, 15AE180719AAD2F700C27E9E /* 3dExport.h in Headers */, 15AE1A2019AAD3A700C27E9E /* spine-cocos2dx.h in Headers */, + 3E2BDAE919C0329B0055CDCD /* AudioPlayer.h in Headers */, 15AE185D19AAD31200C27E9E /* CocosDenshion.h in Headers */, 15AE194319AAD35100C27E9E /* CCColliderDetector.h in Headers */, 15AE1BC419AADFFB00C27E9E /* ExtensionMacros.h in Headers */, @@ -5749,7 +5787,7 @@ 1551A336158F2AB200E66CFE /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0500; + LastUpgradeCheck = 0600; ORGANIZATIONNAME = ""; }; buildConfigurationList = 1551A339158F2AB200E66CFE /* Build configuration list for PBXProject "cocos2d_libs" */; @@ -5985,6 +6023,7 @@ 1A570282180BCC900088DEC7 /* CCSpriteBatchNode.cpp in Sources */, 1A570286180BCC900088DEC7 /* CCSpriteFrame.cpp in Sources */, B24AA989195A675C007B4522 /* CCFastTMXTiledMap.cpp in Sources */, + B60C5BD419AC68B10056FBDE /* CCBillBoard.cpp in Sources */, 15AE199619AAD39600C27E9E /* ListViewReader.cpp in Sources */, 50ABC0191926664800A911A9 /* CCSAXParser.cpp in Sources */, 15AE189219AAD33D00C27E9E /* CCLayerGradientLoader.cpp in Sources */, @@ -6202,6 +6241,7 @@ 50ABBDA01925AB4100A911A9 /* CCGroupCommand.cpp in Sources */, 46A171031807CECB005B8026 /* CCPhysicsShape.cpp in Sources */, 50ABC0161926664800A911A9 /* CCImage.cpp in Sources */, + 3E2BDAE819C0329B0055CDCD /* AudioEngine-inl.mm in Sources */, 1A01C6A518F58F7500EFE3A6 /* CCNotificationCenter.cpp in Sources */, 292DB14E19B4574100A80320 /* UIEditBoxImpl-mac.mm in Sources */, 15AE1BFB19AAE01E00C27E9E /* CCControlUtils.cpp in Sources */, @@ -6230,6 +6270,7 @@ B257B44F1989D5E800D9A687 /* CCPrimitive.cpp in Sources */, 50ABBE281925AB6F00A911A9 /* CCAutoreleasePool.cpp in Sources */, 15AE18D519AAD33D00C27E9E /* CCScale9SpriteLoader.cpp in Sources */, + 3E2BDAEA19C0329B0055CDCD /* AudioPlayer.mm in Sources */, 15AE192919AAD35100C27E9E /* TriggerMng.cpp in Sources */, 15AE185E19AAD31200C27E9E /* CocosDenshion.m in Sources */, 46A170FE1807CECB005B8026 /* CCPhysicsContact.cpp in Sources */, @@ -6390,6 +6431,7 @@ 50ABBDBE1925AB4100A911A9 /* CCTextureCache.cpp in Sources */, 1A5701E3180BCB8C0088DEC7 /* CCScene.cpp in Sources */, 50ABBD611925AB0000A911A9 /* Vec4.cpp in Sources */, + B60C5BD519AC68B10056FBDE /* CCBillBoard.cpp in Sources */, 15AE184519AAD2F700C27E9E /* CCSprite3DMaterial.cpp in Sources */, 50ABBD9C1925AB4100A911A9 /* ccGLStateCache.cpp in Sources */, 1A5701E7180BCB8C0088DEC7 /* CCTransition.cpp in Sources */, @@ -6546,6 +6588,7 @@ 3E6176761960F89B00DE83F5 /* CCEventListenerController.cpp in Sources */, 15AE1AC219AAD40300C27E9E /* b2DistanceJoint.cpp in Sources */, 503DD8E71926736A00CD74DD /* CCEAGLView-ios.mm in Sources */, + 3E2BDAEC19C0436F0055CDCD /* AudioEngine.cpp in Sources */, 50ABBDA41925AB4100A911A9 /* CCQuadCommand.cpp in Sources */, 15AE18C319AAD33D00C27E9E /* CCLayerGradientLoader.cpp in Sources */, 15AE197919AAD35700C27E9E /* CCActionTimelineCache.cpp in Sources */, @@ -6572,6 +6615,7 @@ 15AE18CC19AAD33D00C27E9E /* CCNode+CCBRelativePositioning.cpp in Sources */, 50ABBD5D1925AB0000A911A9 /* Vec3.cpp in Sources */, 50ABC0121926664800A911A9 /* CCGLView.cpp in Sources */, + 3E2BDAE619C0329B0055CDCD /* AudioCache.mm in Sources */, 50ABC0021926664800A911A9 /* CCLock-apple.cpp in Sources */, 50ABBEBC1925AB6F00A911A9 /* ccUtils.cpp in Sources */, 15AE1A4719AAD3D500C27E9E /* b2ChainShape.cpp in Sources */, @@ -6610,7 +6654,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_BOOL_CONVERSION = YES; @@ -6648,7 +6691,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_BOOL_CONVERSION = YES; @@ -6683,7 +6725,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD)"; + COMBINE_HIDPI_IMAGES = YES; EXECUTABLE_EXTENSION = a; EXECUTABLE_PREFIX = ""; GCC_PRECOMPILE_PREFIX_HEADER = YES; @@ -6717,7 +6759,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD)"; + COMBINE_HIDPI_IMAGES = YES; EXECUTABLE_EXTENSION = a; EXECUTABLE_PREFIX = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; @@ -6752,7 +6794,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD)"; EXECUTABLE_PREFIX = ""; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "../cocos/cocos2d-prefix.pch"; @@ -6784,7 +6825,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD)"; EXECUTABLE_PREFIX = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; diff --git a/build/cocos2d_tests.xcodeproj/project.pbxproj b/build/cocos2d_tests.xcodeproj/project.pbxproj index dec67dde2c..20341db71a 100644 --- a/build/cocos2d_tests.xcodeproj/project.pbxproj +++ b/build/cocos2d_tests.xcodeproj/project.pbxproj @@ -871,6 +871,8 @@ 38FA2E74194AEBE100FF2BE4 /* ActionTimelineTestScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 38FA2E71194AEBE100FF2BE4 /* ActionTimelineTestScene.cpp */; }; 38FA2E76194AECF800FF2BE4 /* ActionTimeline in Resources */ = {isa = PBXBuildFile; fileRef = 38FA2E75194AECF800FF2BE4 /* ActionTimeline */; }; 38FA2E77194AECF800FF2BE4 /* ActionTimeline in Resources */ = {isa = PBXBuildFile; fileRef = 38FA2E75194AECF800FF2BE4 /* ActionTimeline */; }; + 3E2BDAD019BEA3410055CDCD /* NewAudioEngineTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3E2BDACE19BEA3410055CDCD /* NewAudioEngineTest.cpp */; }; + 3E2BDAD219BEA3E20055CDCD /* audio in Resources */ = {isa = PBXBuildFile; fileRef = 3E2BDAD119BEA3E20055CDCD /* audio */; }; 3E6177221960FAED00DE83F5 /* libcocos2d iOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 46A15FBE1807A4F9005B8026 /* libcocos2d iOS.a */; }; 3E6177241960FAED00DE83F5 /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D60AE43317F7FFE100757E4B /* CoreMotion.framework */; }; 3E6177251960FAED00DE83F5 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15C6482E165F399D007D4F18 /* libz.dylib */; }; @@ -931,6 +933,8 @@ A07A52C31783B02C0073F6A7 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A07A52C11783B01F0073F6A7 /* AVFoundation.framework */; }; B2507B6B192589AF00FA4972 /* Shaders3D in Resources */ = {isa = PBXBuildFile; fileRef = B2507B6A192589AF00FA4972 /* Shaders3D */; }; B2507B6C192589AF00FA4972 /* Shaders3D in Resources */ = {isa = PBXBuildFile; fileRef = B2507B6A192589AF00FA4972 /* Shaders3D */; }; + B609E67319C18DAD003D0074 /* BillBoardTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B609E67119C18DAD003D0074 /* BillBoardTest.cpp */; }; + B609E67419C18DAD003D0074 /* BillBoardTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B609E67119C18DAD003D0074 /* BillBoardTest.cpp */; }; C04F935A1941B05400E9FEAB /* TileMapTest2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C04F93581941B05400E9FEAB /* TileMapTest2.cpp */; }; C04F935B1941B05400E9FEAB /* TileMapTest2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C04F93581941B05400E9FEAB /* TileMapTest2.cpp */; }; C08689C118D370C90093E810 /* background.caf in Resources */ = {isa = PBXBuildFile; fileRef = C08689C018D370C90093E810 /* background.caf */; }; @@ -2892,6 +2896,9 @@ 38FA2E71194AEBE100FF2BE4 /* ActionTimelineTestScene.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActionTimelineTestScene.cpp; sourceTree = ""; }; 38FA2E72194AEBE100FF2BE4 /* ActionTimelineTestScene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionTimelineTestScene.h; sourceTree = ""; }; 38FA2E75194AECF800FF2BE4 /* ActionTimeline */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ActionTimeline; path = "../tests/cpp-tests/Resources/ActionTimeline"; sourceTree = ""; }; + 3E2BDACE19BEA3410055CDCD /* NewAudioEngineTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewAudioEngineTest.cpp; sourceTree = ""; }; + 3E2BDACF19BEA3410055CDCD /* NewAudioEngineTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewAudioEngineTest.h; sourceTree = ""; }; + 3E2BDAD119BEA3E20055CDCD /* audio */ = {isa = PBXFileReference; lastKnownFileType = folder; name = audio; path = "../tests/cpp-tests/Resources/audio"; sourceTree = ""; }; 3E6176B71960FA6300DE83F5 /* AppDelegate.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AppDelegate.cpp; sourceTree = ""; }; 3E6176B81960FA6300DE83F5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 3E6176B91960FA6300DE83F5 /* AppMacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppMacros.h; sourceTree = ""; }; @@ -2948,6 +2955,8 @@ A07A52BB1783AEB80073F6A7 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; A07A52C11783B01F0073F6A7 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/System/Library/Frameworks/AVFoundation.framework; sourceTree = DEVELOPER_DIR; }; B2507B6A192589AF00FA4972 /* Shaders3D */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Shaders3D; path = "../tests/cpp-tests/Resources/Shaders3D"; sourceTree = ""; }; + B609E67119C18DAD003D0074 /* BillBoardTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BillBoardTest.cpp; path = BillBoardTest/BillBoardTest.cpp; sourceTree = ""; }; + B609E67219C18DAD003D0074 /* BillBoardTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BillBoardTest.h; path = BillBoardTest/BillBoardTest.h; sourceTree = ""; }; C04F93581941B05400E9FEAB /* TileMapTest2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TileMapTest2.cpp; sourceTree = ""; }; C04F93591941B05400E9FEAB /* TileMapTest2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TileMapTest2.h; sourceTree = ""; }; C08689C018D370C90093E810 /* background.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = background.caf; path = "../tests/cpp-tests/Resources/background.caf"; sourceTree = ""; }; @@ -5422,6 +5431,8 @@ 1AC3592418CECF0A00F37B72 /* Classes */ = { isa = PBXGroup; children = ( + B609E67019C18D90003D0074 /* BillBoardTest */, + 3E2BDACD19BEA3410055CDCD /* NewAudioEngineTest */, 3E9E75CB199324A8005B7047 /* Camera3DTest */, 1AC3592818CECF0A00F37B72 /* ActionManagerTest */, 1AC3592B18CECF0A00F37B72 /* ActionsEaseTest */, @@ -6445,6 +6456,7 @@ 1AC35CA818CED83500F37B72 /* Resources */ = { isa = PBXGroup; children = ( + 3E2BDAD119BEA3E20055CDCD /* audio */, 38FA2E75194AECF800FF2BE4 /* ActionTimeline */, B2507B6A192589AF00FA4972 /* Shaders3D */, 3E92EA841921A7720094CD21 /* Sprite3DTest */, @@ -7026,6 +7038,15 @@ path = CocoStudioActionTimelineTest; sourceTree = ""; }; + 3E2BDACD19BEA3410055CDCD /* NewAudioEngineTest */ = { + isa = PBXGroup; + children = ( + 3E2BDACE19BEA3410055CDCD /* NewAudioEngineTest.cpp */, + 3E2BDACF19BEA3410055CDCD /* NewAudioEngineTest.h */, + ); + path = NewAudioEngineTest; + sourceTree = ""; + }; 3E6176B51960FA6300DE83F5 /* game-controller-test */ = { isa = PBXGroup; children = ( @@ -7125,6 +7146,15 @@ name = Products; sourceTree = ""; }; + B609E67019C18D90003D0074 /* BillBoardTest */ = { + isa = PBXGroup; + children = ( + B609E67119C18DAD003D0074 /* BillBoardTest.cpp */, + B609E67219C18DAD003D0074 /* BillBoardTest.h */, + ); + name = BillBoardTest; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -7319,7 +7349,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0510; + LastUpgradeCheck = 0600; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "cocos2d_tests" */; compatibilityVersion = "Xcode 3.2"; @@ -7814,6 +7844,7 @@ 1AC35CD518CED84500F37B72 /* ccb in Resources */, 1AC35CE118CED84500F37B72 /* configs in Resources */, 1AC35CE918CED84500F37B72 /* extensions in Resources */, + 3E2BDAD219BEA3E20055CDCD /* audio in Resources */, C08689C318D370C90093E810 /* background.caf in Resources */, 1AC35C9518CECF1400F37B72 /* Icon-72.png in Resources */, 1AC35D0B18CED84500F37B72 /* zwoptex in Resources */, @@ -8016,6 +8047,7 @@ 1AC35B7D18CECF0C00F37B72 /* PlayerController.cpp in Sources */, 29080D9F191B595E0066F8DF /* CustomReader.cpp in Sources */, 1AC35BE718CECF0C00F37B72 /* CCControlScene.cpp in Sources */, + B609E67319C18DAD003D0074 /* BillBoardTest.cpp in Sources */, 292CF01419A1965E00E8E6A0 /* UIEditBoxTest.cpp in Sources */, 29080DBF191B595E0066F8DF /* UIPageViewTest_Editor.cpp in Sources */, 1AC35B5F18CECF0C00F37B72 /* DataVisitorTest.cpp in Sources */, @@ -8200,10 +8232,12 @@ 292CF01519A1965E00E8E6A0 /* UIEditBoxTest.cpp in Sources */, 1AC35B2818CECF0C00F37B72 /* ActionsTest.cpp in Sources */, 1AC35C4A18CECF0C00F37B72 /* ShaderTest.cpp in Sources */, + B609E67419C18DAD003D0074 /* BillBoardTest.cpp in Sources */, C04F935B1941B05400E9FEAB /* TileMapTest2.cpp in Sources */, 1AC35B4418CECF0C00F37B72 /* Bug-624.cpp in Sources */, 1AC35BF818CECF0C00F37B72 /* SocketIOTest.cpp in Sources */, 1AC35C5018CECF0C00F37B72 /* SpriteTest.cpp in Sources */, + 3E2BDAD019BEA3410055CDCD /* NewAudioEngineTest.cpp in Sources */, 1AC35C0418CECF0C00F37B72 /* FileUtilsTest.cpp in Sources */, 1AC35B5C18CECF0C00F37B72 /* CurlTest.cpp in Sources */, 1AC35C0018CECF0C00F37B72 /* CustomTableViewCell.cpp in Sources */, @@ -8557,7 +8591,6 @@ 1A0EE2B018CDF6DA004CD58F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", @@ -8572,7 +8605,6 @@ 1A0EE2B118CDF6DA004CD58F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", @@ -8588,7 +8620,6 @@ 1A0EE31218CDF733004CD58F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", CC_TARGET_OS_MAC, @@ -8608,7 +8639,6 @@ 1A0EE31318CDF733004CD58F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", CC_TARGET_OS_MAC, @@ -8703,7 +8733,6 @@ 1ABCA2B318CD91520087CE3A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", CC_TARGET_OS_MAC, @@ -8723,7 +8752,6 @@ 1ABCA2B418CD91520087CE3A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", CC_TARGET_OS_MAC, @@ -8785,7 +8813,6 @@ 1D6058940D05DD3E006BFB54 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", CC_TARGET_OS_MAC, @@ -8799,7 +8826,6 @@ 1D6058950D05DD3E006BFB54 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", CC_TARGET_OS_MAC, diff --git a/cocos/2d/CCNodeGrid.cpp b/cocos/2d/CCNodeGrid.cpp index eb42030199..2153b9dca2 100644 --- a/cocos/2d/CCNodeGrid.cpp +++ b/cocos/2d/CCNodeGrid.cpp @@ -150,8 +150,9 @@ void NodeGrid::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t p this->draw(renderer, _modelViewTransform, dirty); } - // reset for next frame - _orderOfArrival = 0; + // FIX ME: Why need to set _orderOfArrival to 0?? + // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920 + // setOrderOfArrival(0); if(_nodeGrid && _nodeGrid->isActive()) { diff --git a/cocos/2d/CCProtectedNode.cpp b/cocos/2d/CCProtectedNode.cpp index d65ca6a7b5..3a8259b48d 100644 --- a/cocos/2d/CCProtectedNode.cpp +++ b/cocos/2d/CCProtectedNode.cpp @@ -330,8 +330,9 @@ void ProtectedNode::visit(Renderer* renderer, const Mat4 &parentTransform, uint3 for(auto it=_children.cbegin()+i; it != _children.cend(); ++it) (*it)->visit(renderer, _modelViewTransform, flags); - // reset for next frame - _orderOfArrival = 0; + // FIX ME: Why need to set _orderOfArrival to 0?? + // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920 + // setOrderOfArrival(0); director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); } diff --git a/cocos/2d/CCRenderTexture.cpp b/cocos/2d/CCRenderTexture.cpp index 13fed5a85e..201cf0cfc1 100644 --- a/cocos/2d/CCRenderTexture.cpp +++ b/cocos/2d/CCRenderTexture.cpp @@ -403,7 +403,9 @@ void RenderTexture::visit(Renderer *renderer, const Mat4 &parentTransform, uint3 director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); - _orderOfArrival = 0; + // FIX ME: Why need to set _orderOfArrival to 0?? + // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920 + // setOrderOfArrival(0); } bool RenderTexture::saveToFile(const std::string& filename, bool isRGBA, std::function callback) diff --git a/cocos/2d/cocos2d_headers.props b/cocos/2d/cocos2d_headers.props index aaaefd1c7d..06da521592 100644 --- a/cocos/2d/cocos2d_headers.props +++ b/cocos/2d/cocos2d_headers.props @@ -7,7 +7,7 @@ - $(EngineRoot)cocos;$(EngineRoot)cocos\platform\win32;$(EngineRoot)cocos\platform\desktop;$(EngineRoot)external\glfw3\include\win32;$(EngineRoot)external\win32-specific\gles\include\OGLES + $(EngineRoot)cocos;$(EngineRoot)cocos\platform;$(EngineRoot)cocos\platform\desktop;$(EngineRoot)external\glfw3\include\win32;$(EngineRoot)external\win32-specific\gles\include\OGLES _VARIADIC_MAX=10;%(PreprocessorDefinitions) diff --git a/cocos/2d/libcocos2d.vcxproj b/cocos/2d/libcocos2d.vcxproj index 4e05730a3e..29947770a4 100644 --- a/cocos/2d/libcocos2d.vcxproj +++ b/cocos/2d/libcocos2d.vcxproj @@ -205,6 +205,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.* + @@ -540,6 +541,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.* + diff --git a/cocos/2d/libcocos2d.vcxproj.filters b/cocos/2d/libcocos2d.vcxproj.filters index dfcdb7b987..92e64a5b72 100644 --- a/cocos/2d/libcocos2d.vcxproj.filters +++ b/cocos/2d/libcocos2d.vcxproj.filters @@ -1105,6 +1105,9 @@ cocosbuilder\Source Files + + 3d + ui\UIWidgets\EditBox @@ -2224,6 +2227,9 @@ cocosbuilder\Header Files + + 3d + ui\UIWidgets\EditBox diff --git a/cocos/3d/Android.mk b/cocos/3d/Android.mk index 0a9d859a27..c0ce7c55f3 100644 --- a/cocos/3d/Android.mk +++ b/cocos/3d/Android.mk @@ -12,6 +12,7 @@ CCOBB.cpp \ CCAnimate3D.cpp \ CCAnimation3D.cpp \ CCAttachNode.cpp \ +CCBillBoard.cpp \ CCBundle3D.cpp \ CCBundleReader.cpp \ CCMesh.cpp \ diff --git a/cocos/3d/CCBillBoard.cpp b/cocos/3d/CCBillBoard.cpp new file mode 100644 index 0000000000..79fc733553 --- /dev/null +++ b/cocos/3d/CCBillBoard.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "3d/CCBillBoard.h" +#include "2d/CCSpriteFrameCache.h" +#include "base/CCDirector.h" +#include "base/CCCamera.h" +#include "renderer/CCRenderer.h" +#include "renderer/CCGLProgramCache.h" + +NS_CC_BEGIN + +BillBoard::BillBoard() +: _zDepthInView(0.0f) +, _mode(Mode::VIEW_POINT_ORIENTED) +, _modeDirty(false) +{ + +} + +BillBoard::~BillBoard() +{ +} + +BillBoard* BillBoard::createWithTexture(Texture2D *texture, Mode mode) +{ + BillBoard *billborad = new (std::nothrow) BillBoard(); + if (billborad && billborad->initWithTexture(texture)) + { + billborad->_mode = mode; + billborad->autorelease(); + return billborad; + } + CC_SAFE_DELETE(billborad); + return nullptr; +} + + +BillBoard* BillBoard::create(const std::string& filename, Mode mode) +{ + BillBoard *billborad = new (std::nothrow) BillBoard(); + if (billborad && billborad->initWithFile(filename)) + { + billborad->_mode = mode; + billborad->autorelease(); + return billborad; + } + CC_SAFE_DELETE(billborad); + return nullptr; +} + +BillBoard* BillBoard::create(const std::string& filename, const Rect& rect, Mode mode) +{ + BillBoard *billborad = new (std::nothrow) BillBoard(); + if (billborad && billborad->initWithFile(filename, rect)) + { + billborad->_mode = mode; + billborad->autorelease(); + return billborad; + } + CC_SAFE_DELETE(billborad); + return nullptr; +} + +BillBoard* BillBoard::create(Mode mode) +{ + BillBoard *billborad = new (std::nothrow) BillBoard(); + if (billborad && billborad->init()) + { + billborad->_mode = mode; + billborad->autorelease(); + return billborad; + } + CC_SAFE_DELETE(billborad); + return nullptr; +} + +void BillBoard::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) +{ + auto camera = Camera::getVisitingCamera(); + + const Mat4& camWorldMat = camera->getNodeToWorldTransform(); + if (memcmp(_camWorldMat.m, camWorldMat.m, sizeof(float) * 16) != 0 || memcmp(_transform.m, transform.m, sizeof(float) * 16) != 0 || _modeDirty) + { + Vec3 camDir; + switch (_mode) + { + case Mode::VIEW_POINT_ORIENTED: + camDir = Vec3(transform.m[12] - camWorldMat.m[12], transform.m[13] - camWorldMat.m[13], transform.m[14] - camWorldMat.m[14]); + break; + case Mode::VIEW_PLANE_ORIENTED: + camWorldMat.transformVector(Vec3(0.0f, 0.0f, -1.0f), &camDir); + break; + default: + CCASSERT(false, "invalid billboard mode"); + break; + } + _modeDirty = false; + + if (camDir.length() < MATH_TOLERANCE) + { + camDir.set(camWorldMat.m[8], camWorldMat.m[9], camWorldMat.m[10]); + } + camDir.normalize(); + + static Vec3 upAxis(0.0f, 1.0f, 0.0f); + Vec3 x, y; + camWorldMat.transformVector(upAxis, &y); + Vec3::cross(camDir, y, &x); + x.normalize(); + Vec3::cross(x, camDir, &y); + float xlen = sqrtf(transform.m[0] * transform.m[0] + transform.m[1] * transform.m[1] + transform.m[2] * transform.m[2]); + float ylen = sqrtf(transform.m[4] * transform.m[4] + transform.m[5] * transform.m[5] + transform.m[6] * transform.m[6]); + float zlen = sqrtf(transform.m[8] * transform.m[8] + transform.m[9] * transform.m[9] + transform.m[10] * transform.m[10]); + + _billboardTransform.m[0] = x.x * xlen; _billboardTransform.m[1] = x.y * xlen; _billboardTransform.m[2] = x.z * xlen; + _billboardTransform.m[4] = y.x * ylen; _billboardTransform.m[5] = y.y * ylen; _billboardTransform.m[6] = y.z * ylen; + _billboardTransform.m[8] = -camDir.x * zlen; _billboardTransform.m[9] = -camDir.y * zlen; _billboardTransform.m[10] = -camDir.z * zlen; + _billboardTransform.m[12] = transform.m[12]; _billboardTransform.m[13] = transform.m[13]; _billboardTransform.m[14] = transform.m[14]; + + const Mat4 &viewMat = camWorldMat.getInversed(); + _zDepthInView = -(viewMat.m[2] * transform.m[12] + viewMat.m[6] * transform.m[13] + viewMat.m[10] * transform.m[14] + viewMat.m[14]); + _transform = transform; + _camWorldMat = camWorldMat; + } + + //FIXME: frustum culling here + { + _quadCommand.init(_zDepthInView, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, _billboardTransform); + renderer->addCommandToTransparentQueue(&_quadCommand); + } +} + +void BillBoard::setMode( Mode mode ) +{ + _mode = mode; + _modeDirty = true; +} + +BillBoard::Mode BillBoard::getMode() const +{ + return _mode; +} + +NS_CC_END diff --git a/cocos/3d/CCBillBoard.h b/cocos/3d/CCBillBoard.h new file mode 100644 index 0000000000..a96fa15ed7 --- /dev/null +++ b/cocos/3d/CCBillBoard.h @@ -0,0 +1,121 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#ifndef __CCBILLBOARD_H__ +#define __CCBILLBOARD_H__ + +#include "2d/CCSprite.h" +#include "3d/3dExport.h" + +NS_CC_BEGIN + +/** + * Inherit from Sprite, achieve BillBoard. + */ +class CC_3D_DLL BillBoard : public Sprite +{ +public: + + enum class Mode + { + VIEW_POINT_ORIENTED, // orient to the camera + VIEW_PLANE_ORIENTED // orient to the XOY plane of camera + }; + /// @{ + /// @name Creators + + /** + * Creates an empty BillBoard without texture. You can call setTexture method subsequently. + * + * @return An autoreleased BillBoard object. + */ + static BillBoard* create(Mode mode = Mode::VIEW_POINT_ORIENTED); + + /** + * Creates a BillBoard with an image filename. + * + * After creation, the rect of BillBoard will be the size of the image, + * and the offset will be (0,0). + * + * @param filename A path to image file, e.g., "scene1/monster.png" + * @return An autoreleased BillBoard object. + */ + static BillBoard* create(const std::string& filename, Mode mode = Mode::VIEW_POINT_ORIENTED); + + /** + * Creates a BillBoard with an image filename and a rect. + * + * @param filename A path to image file, e.g., "scene1/monster.png" + * @param rect A subrect of the image file + * @return An autoreleased BillBoard object + */ + static BillBoard* create(const std::string& filename, const Rect& rect, Mode mode = Mode::VIEW_POINT_ORIENTED); + + /** + * Creates a BillBoard with a Texture2D object. + * + * After creation, the rect will be the size of the texture, and the offset will be (0,0). + * + * @param texture A pointer to a Texture2D object. + * @return An autoreleased BillBoard object + */ + static BillBoard* createWithTexture(Texture2D *texture, Mode mode = Mode::VIEW_POINT_ORIENTED); + + /** Set the billboard rotation mode. */ + void setMode(Mode mode); + + /** Get the billboard rotation mode. */ + Mode getMode() const; + + //override + /** draw BillBoard object */ + virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override; + + +CC_CONSTRUCTOR_ACCESS: + BillBoard(); + virtual ~BillBoard(); + +protected: + + Mat4 _camWorldMat; + Mat4 _transform; + Mat4 _billboardTransform; + + float _zDepthInView; + + Mode _mode; + bool _modeDirty; + +private: + CC_DISALLOW_COPY_AND_ASSIGN(BillBoard); + +}; + + + +NS_CC_END + + +#endif // __CCBILLBOARD_H__ diff --git a/cocos/Android.mk b/cocos/Android.mk index 08873fb606..4b9ded3248 100644 --- a/cocos/Android.mk +++ b/cocos/Android.mk @@ -187,7 +187,7 @@ physics/chipmunk/CCPhysicsWorldInfo_chipmunk.cpp \ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) \ $(LOCAL_PATH)/. \ - $(LOCAL_PATH)/platform/android \ + $(LOCAL_PATH)/platform \ $(LOCAL_PATH)/base \ $(LOCAL_PATH)/../external/tinyxml2 \ $(LOCAL_PATH)/../external/unzip \ @@ -197,7 +197,7 @@ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) \ LOCAL_C_INCLUDES := $(LOCAL_PATH) \ $(LOCAL_PATH)/. \ - $(LOCAL_PATH)/platform/android \ + $(LOCAL_PATH)/platform \ $(LOCAL_PATH)/../external \ $(LOCAL_PATH)/../external/tinyxml2 \ $(LOCAL_PATH)/../external/unzip \ @@ -238,6 +238,7 @@ LOCAL_MODULE := cocos2dx_static LOCAL_MODULE_FILENAME := libcocos2d LOCAL_STATIC_LIBRARIES := cocostudio_static +LOCAL_STATIC_LIBRARIES += audioengine_static LOCAL_STATIC_LIBRARIES += cocos3d_static LOCAL_STATIC_LIBRARIES += cocosbuilder_static LOCAL_STATIC_LIBRARIES += spine_static diff --git a/cocos/CMakeLists.txt b/cocos/CMakeLists.txt index e1d889b96c..124a798d00 100644 --- a/cocos/CMakeLists.txt +++ b/cocos/CMakeLists.txt @@ -192,6 +192,7 @@ set(COCOS2D_BASE_SRC 3d/CCSkeleton3D.cpp 3d/CCSprite3D.cpp 3d/CCSprite3DMaterial.cpp + 3d/CCBillBoard.cpp network/HttpClient.cpp network/SocketIO.cpp @@ -296,7 +297,7 @@ if(MACOSX) ${COCOS2D_BASE_SRC} ui/UIEditBox/UIEditBoxImpl-ios.mm ui/UIEditBox/UIEditBoxImpl-mac.mm - base/CCUserDefault.mm + base/CCUserDefault-apple.mm ) endif() diff --git a/cocos/audio/AudioEngine.cpp b/cocos/audio/AudioEngine.cpp new file mode 100644 index 0000000000..03579936bf --- /dev/null +++ b/cocos/audio/AudioEngine.cpp @@ -0,0 +1,395 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS + +#include "audio/include/AudioEngine.h" +#include "platform/CCFileUtils.h" +#include "base/ccUtils.h" + +#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID +#include "android/AudioEngine-inl.h" +#elif CC_TARGET_PLATFORM == CC_PLATFORM_IOS +#include "ios/AudioEngine-inl.h" +#endif + +#define TIME_DELAY_PRECISION 0.0001 + +using namespace cocos2d; + +const int AudioEngine::INVAILD_AUDIO_ID = -1; +const float AudioEngine::TIME_UNKNOWN = -1.0f; + +//audio file path,audio IDs +std::unordered_map> AudioEngine::_audioPathIDMap; +//profileName,ProfileHelper +std::unordered_map AudioEngine::_audioPathProfileHelperMap; +int AudioEngine::_maxInstances = MAX_AUDIOINSTANCES; +AudioEngine::ProfileHelper* AudioEngine::_defaultProfileHelper; +std::unordered_map AudioEngine::_audioIDInfoMap; +AudioEngineImpl* AudioEngine::_audioEngineImpl = nullptr; + +void AudioEngine::end() +{ + delete _audioEngineImpl; + _audioEngineImpl = nullptr; + + delete _defaultProfileHelper; + _defaultProfileHelper = nullptr; +} + +bool AudioEngine::lazyInit() +{ + if (_audioEngineImpl == nullptr) + { + _audioEngineImpl = new (std::nothrow) AudioEngineImpl(); + if(!_audioEngineImpl || !_audioEngineImpl->init() ){ + return false; + } + } + + return true; +} + +int AudioEngine::play2d(const std::string& filePath, bool loop, float volume, const AudioProfile *profile) +{ + int ret = AudioEngine::INVAILD_AUDIO_ID; + + do { + if ( !lazyInit() ){ + break; + } + + if ( !FileUtils::getInstance()->isFileExist(filePath)){ + break; + } + + ProfileHelper* manage = _defaultProfileHelper; + if (profile && profile != &manage->profile){ + CC_ASSERT(!profile->name.empty()); + manage = &_audioPathProfileHelperMap[profile->name]; + manage->profile = *profile; + } + + if (_audioIDInfoMap.size() >= _maxInstances) { + log("Fail to play %s cause by limited max instance of AudioEngine",filePath.c_str()); + break; + } + if (manage) + { + if(manage->profile.maxInstances != 0 && manage->audioIDs.size() >= manage->profile.maxInstances){ + log("Fail to play %s cause by limited max instance of AudioProfile",filePath.c_str()); + break; + } + if (manage->profile.minDelay > TIME_DELAY_PRECISION) { + auto currTime = utils::gettime(); + if (manage->lastPlayTime > TIME_DELAY_PRECISION && currTime - manage->lastPlayTime <= manage->profile.minDelay) { + log("Fail to play %s cause by limited minimum delay",filePath.c_str()); + break; + } + } + } + + if (volume < 0.0f) { + volume = 0.0f; + } + else if (volume > 1.0f){ + volume = 1.0f; + } + + ret = _audioEngineImpl->play2d(filePath, loop, volume); + if (ret != INVAILD_AUDIO_ID) + { + _audioPathIDMap[filePath].push_back(ret); + auto it = _audioPathIDMap.find(filePath); + + auto& audioRef = _audioIDInfoMap[ret]; + audioRef.volume = volume; + audioRef.loop = loop; + audioRef.is3dAudio = false; + audioRef.filePath = &it->first; + + if (manage) { + manage->lastPlayTime = utils::gettime(); + manage->audioIDs.push_back(ret); + } + audioRef.profileHelper = manage; + } + } while (0); + + return ret; +} + +void AudioEngine::setLoop(int audioID, bool loop) +{ + auto it = _audioIDInfoMap.find(audioID); + if (it != _audioIDInfoMap.end() && it->second.loop != loop){ + _audioEngineImpl->setLoop(audioID, loop); + it->second.loop = loop; + } +} + +void AudioEngine::setVolume(int audioID, float volume) +{ + auto it = _audioIDInfoMap.find(audioID); + if (it != _audioIDInfoMap.end()){ + if (volume < 0.0f) { + volume = 0.0f; + } + else if (volume > 1.0f){ + volume = 1.0f; + } + + if (it->second.volume != volume){ + _audioEngineImpl->setVolume(audioID, volume); + it->second.volume = volume; + } + } +} + +void AudioEngine::pause(int audioID) +{ + auto it = _audioIDInfoMap.find(audioID); + if (it != _audioIDInfoMap.end() && it->second.state == AudioState::PLAYING){ + _audioEngineImpl->pause(audioID); + it->second.state = AudioState::PAUSED; + } +} + +void AudioEngine::pauseAll() +{ + auto itEnd = _audioIDInfoMap.end(); + for (auto it = _audioIDInfoMap.begin(); it != itEnd; ++it) + { + if (it->second.state == AudioState::PLAYING) + { + _audioEngineImpl->pause(it->first); + it->second.state = AudioState::PAUSED; + } + } +} + +void AudioEngine::resume(int audioID) +{ + auto it = _audioIDInfoMap.find(audioID); + if (it != _audioIDInfoMap.end() && it->second.state == AudioState::PAUSED){ + _audioEngineImpl->resume(audioID); + it->second.state = AudioState::PLAYING; + } +} + +void AudioEngine::resumeAll() +{ + auto itEnd = _audioIDInfoMap.end(); + for (auto it = _audioIDInfoMap.begin(); it != itEnd; ++it) + { + if (it->second.state == AudioState::PAUSED) + { + _audioEngineImpl->resume(it->first); + it->second.state = AudioState::PLAYING; + } + } +} + +void AudioEngine::stop(int audioID) +{ + auto it = _audioIDInfoMap.find(audioID); + if (it != _audioIDInfoMap.end()){ + _audioEngineImpl->stop(audioID); + + remove(audioID); + } +} + +void AudioEngine::remove(int audioID) +{ + auto it = _audioIDInfoMap.find(audioID); + if (it != _audioIDInfoMap.end()){ + if (it->second.profileHelper) { + it->second.profileHelper->audioIDs.remove(audioID); + } + _audioPathIDMap[*it->second.filePath].remove(audioID); + _audioIDInfoMap.erase(audioID); + } +} + +void AudioEngine::stopAll() +{ + _audioEngineImpl->stopAll(); + auto itEnd = _audioIDInfoMap.end(); + for (auto it = _audioIDInfoMap.begin(); it != itEnd; ++it) + { + if (it->second.profileHelper){ + it->second.profileHelper->audioIDs.remove(it->first); + } + } + _audioPathIDMap.clear(); + _audioIDInfoMap.clear(); +} + +void AudioEngine::uncache(const std::string &filePath) +{ + if(_audioPathIDMap.find(filePath) != _audioPathIDMap.end()){ + auto itEnd = _audioPathIDMap[filePath].end(); + for (auto it = _audioPathIDMap[filePath].begin() ; it != itEnd; ++it) { + auto audioID = *it; + _audioEngineImpl->stop(audioID); + + auto itInfo = _audioIDInfoMap.find(audioID); + if (itInfo != _audioIDInfoMap.end()){ + if (itInfo->second.profileHelper) { + itInfo->second.profileHelper->audioIDs.remove(audioID); + } + _audioIDInfoMap.erase(audioID); + } + } + _audioEngineImpl->uncache(filePath); + _audioPathIDMap.erase(filePath); + } +} + +void AudioEngine::uncacheAll() +{ + stopAll(); + _audioEngineImpl->uncacheAll(); +} + +float AudioEngine::getDuration(int audioID) +{ + auto it = _audioIDInfoMap.find(audioID); + if (it != _audioIDInfoMap.end() && it->second.state != AudioState::INITIALZING) + { + if (it->second.duration == TIME_UNKNOWN) + { + it->second.duration = _audioEngineImpl->getDuration(audioID); + } + return it->second.duration; + } + + return TIME_UNKNOWN; +} + +bool AudioEngine::setCurrentTime(int audioID, float time) +{ + auto it = _audioIDInfoMap.find(audioID); + if (it != _audioIDInfoMap.end() && it->second.state != AudioState::INITIALZING){ + return _audioEngineImpl->setCurrentTime(audioID, time); + } + + return false; +} + +float AudioEngine::getCurrentTime(int audioID) +{ + auto it = _audioIDInfoMap.find(audioID); + if (it != _audioIDInfoMap.end() && it->second.state != AudioState::INITIALZING){ + return _audioEngineImpl->getCurrentTime(audioID); + } + return 0.0f; +} + +void AudioEngine::setFinishCallback(int audioID, const std::function &callback) +{ + auto it = _audioIDInfoMap.find(audioID); + if (it != _audioIDInfoMap.end()){ + _audioEngineImpl->setFinishCallback(audioID, callback); + } +} + +bool AudioEngine::setMaxAudioInstance(int maxInstances) +{ + if (maxInstances > 0 && maxInstances <= MAX_AUDIOINSTANCES) { + _maxInstances = maxInstances; + return true; + } + + return false; +} + +bool AudioEngine::isLoop(int audioID) +{ + auto tmpIterator = _audioIDInfoMap.find(audioID); + if (tmpIterator != _audioIDInfoMap.end()) + { + return tmpIterator->second.loop; + } + + log("AudioEngine::isLoop-->The audio instance %d is non-existent", audioID); + return false; +} + +float AudioEngine::getVolume(int audioID) +{ + auto tmpIterator = _audioIDInfoMap.find(audioID); + if (tmpIterator != _audioIDInfoMap.end()) + { + return tmpIterator->second.volume; + } + + log("AudioEngine::getVolume-->The audio instance %d is non-existent", audioID); + return 0.0f; +} + +AudioEngine::AudioState AudioEngine::getState(int audioID) +{ + auto tmpIterator = _audioIDInfoMap.find(audioID); + if (tmpIterator != _audioIDInfoMap.end()) + { + return tmpIterator->second.state; + } + + return AudioState::ERROR; +} + +AudioProfile* AudioEngine::getProfile(int audioID) +{ + auto it = _audioIDInfoMap.find(audioID); + if (it != _audioIDInfoMap.end()) + { + return &it->second.profileHelper->profile; + } + + return nullptr; +} + +AudioProfile* AudioEngine::getDefaultProfile() +{ + if (_defaultProfileHelper == nullptr) + { + _defaultProfileHelper = new (std::nothrow) ProfileHelper(); + } + + return &_defaultProfileHelper->profile; +} + +AudioProfile* AudioEngine::getProfile(const std::string &name) +{ + auto it = _audioPathProfileHelperMap.find(name); + if (it != _audioPathProfileHelperMap.end()) { + return &it->second.profile; + } else { + return nullptr; + } +} + +#endif diff --git a/cocos/audio/android/Android.mk b/cocos/audio/android/Android.mk index 3854fa79d7..bbd7725d9d 100644 --- a/cocos/audio/android/Android.mk +++ b/cocos/audio/android/Android.mk @@ -16,3 +16,23 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include \ $(LOCAL_PATH)/../../platform/android include $(BUILD_STATIC_LIBRARY) + +#new audio engine +include $(CLEAR_VARS) + +LOCAL_MODULE := audioengine_static + +LOCAL_MODULE_FILENAME := libaudioengine + +LOCAL_SRC_FILES := AudioEngine-inl.cpp \ + ../AudioEngine.cpp + +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../include + +LOCAL_EXPORT_LDLIBS := -lOpenSLES + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include \ + $(LOCAL_PATH)/../.. \ + $(LOCAL_PATH)/../../platform/android + +include $(BUILD_STATIC_LIBRARY) diff --git a/cocos/audio/android/AudioEngine-inl.cpp b/cocos/audio/android/AudioEngine-inl.cpp new file mode 100644 index 0000000000..69389ab05e --- /dev/null +++ b/cocos/audio/android/AudioEngine-inl.cpp @@ -0,0 +1,366 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID +#include "AudioEngine-inl.h" + +#include +// for native asset manager +#include +#include +#include + +#include "audio/include/AudioEngine.h" +#include "base/CCDirector.h" +#include "platform/android/CCFileUtils-android.h" + +#include "platform/android/jni/JniHelper.h" +#include +#include + +using namespace cocos2d; + +void PlayOverEvent(SLPlayItf caller, void* context, SLuint32 playEvent) +{ + if (context && playEvent == SL_PLAYEVENT_HEADATEND) + { + AudioEngineImpl* engineImpl = (AudioEngineImpl*)context; + engineImpl->playerFinishCallback(caller,playEvent); + } +} + +AudioPlayer::AudioPlayer() + : _fdPlayerObject(nullptr) + , _finishCallback(nullptr) + , _duration(0.0f) +{ + +} + +AudioPlayer::~AudioPlayer() +{ + if (_fdPlayerObject) + { + (*_fdPlayerObject)->Destroy(_fdPlayerObject); + _fdPlayerObject = nullptr; + } +} + +bool AudioPlayer::init(SLEngineItf engineEngine, SLObjectItf outputMixObject,const std::string& fileFullPath, float volume, bool loop) +{ + bool ret = false; + + do + { + SLDataSource audioSrc; + + SLDataLocator_AndroidFD loc_fd; + SLDataLocator_URI loc_uri; + + SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED}; + audioSrc.pFormat = &format_mime; + + if (fileFullPath[0] != '/'){ + std::string relativePath = ""; + + size_t position = fileFullPath.find("assets/"); + if (0 == position) { + // "assets/" is at the beginning of the path and we don't want it + relativePath += fileFullPath.substr(strlen("assets/")); + } else { + relativePath += fileFullPath; + } + + auto asset = AAssetManager_open(cocos2d::FileUtilsAndroid::getAssetManager(), relativePath.c_str(), AASSET_MODE_UNKNOWN); + + // open asset as file descriptor + off_t start, length; + int fd = AAsset_openFileDescriptor(asset, &start, &length); + if (fd <= 0){ + AAsset_close(asset); + break; + } + AAsset_close(asset); + + // configure audio source + loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length}; + + audioSrc.pLocator = &loc_fd; + } + else{ + loc_uri = {SL_DATALOCATOR_URI , (SLchar*)fileFullPath.c_str()}; + audioSrc.pLocator = &loc_uri; + } + + // configure audio sink + SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; + SLDataSink audioSnk = {&loc_outmix, NULL}; + + // create audio player + const SLInterfaceID ids[3] = {SL_IID_SEEK, SL_IID_PREFETCHSTATUS, SL_IID_VOLUME}; + const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; + auto result = (*engineEngine)->CreateAudioPlayer(engineEngine, &_fdPlayerObject, &audioSrc, &audioSnk, 3, ids, req); + if(SL_RESULT_SUCCESS != result){ ERRORLOG("create audio player fail"); break; } + + // realize the player + result = (*_fdPlayerObject)->Realize(_fdPlayerObject, SL_BOOLEAN_FALSE); + if(SL_RESULT_SUCCESS != result){ ERRORLOG("realize the player fail"); break; } + + // get the play interface + result = (*_fdPlayerObject)->GetInterface(_fdPlayerObject, SL_IID_PLAY, &_fdPlayerPlay); + if(SL_RESULT_SUCCESS != result){ ERRORLOG("get the play interface fail"); break; } + + // get the seek interface + result = (*_fdPlayerObject)->GetInterface(_fdPlayerObject, SL_IID_SEEK, &_fdPlayerSeek); + if(SL_RESULT_SUCCESS != result){ ERRORLOG("get the seek interface fail"); break; } + + // get the volume interface + result = (*_fdPlayerObject)->GetInterface(_fdPlayerObject, SL_IID_VOLUME, &_fdPlayerVolume); + if(SL_RESULT_SUCCESS != result){ ERRORLOG("get the volume interface fail"); break; } + + if (loop){ + (*_fdPlayerSeek)->SetLoop(_fdPlayerSeek, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN); + } + + int dbVolume = 2000 * log10(volume); + if(dbVolume < SL_MILLIBEL_MIN){ + dbVolume = SL_MILLIBEL_MIN; + } + (*_fdPlayerVolume)->SetVolumeLevel(_fdPlayerVolume, dbVolume); + + result = (*_fdPlayerPlay)->SetPlayState(_fdPlayerPlay, SL_PLAYSTATE_PLAYING); + if(SL_RESULT_SUCCESS != result){ ERRORLOG("SetPlayState fail"); break; } + + ret = true; + } while (0); + + return ret; +} + +//==================================================== +AudioEngineImpl::AudioEngineImpl() + : currentAudioID(0) + , _engineObject(nullptr) + , _engineEngine(nullptr) + , _outputMixObject(nullptr) +{ + +} + +AudioEngineImpl::~AudioEngineImpl() +{ + if (_outputMixObject) + { + (*_outputMixObject)->Destroy(_outputMixObject); + } + if (_engineObject) + { + (*_engineObject)->Destroy(_engineObject); + } +} + +bool AudioEngineImpl::init() +{ + bool ret = false; + do{ + // create engine + auto result = slCreateEngine(&_engineObject, 0, nullptr, 0, nullptr, nullptr); + if(SL_RESULT_SUCCESS != result){ ERRORLOG("create opensl engine fail"); break; } + + // realize the engine + result = (*_engineObject)->Realize(_engineObject, SL_BOOLEAN_FALSE); + if(SL_RESULT_SUCCESS != result){ ERRORLOG("realize the engine fail"); break; } + + // get the engine interface, which is needed in order to create other objects + result = (*_engineObject)->GetInterface(_engineObject, SL_IID_ENGINE, &_engineEngine); + if(SL_RESULT_SUCCESS != result){ ERRORLOG("get the engine interface fail"); break; } + + // create output mix + const SLInterfaceID outputMixIIDs[] = {}; + const SLboolean outputMixReqs[] = {}; + result = (*_engineEngine)->CreateOutputMix(_engineEngine, &_outputMixObject, 0, outputMixIIDs, outputMixReqs); + if(SL_RESULT_SUCCESS != result){ ERRORLOG("create output mix fail"); break; } + + // realize the output mix + result = (*_outputMixObject)->Realize(_outputMixObject, SL_BOOLEAN_FALSE); + if(SL_RESULT_SUCCESS != result){ ERRORLOG("realize the output mix fail"); break; } + + ret = true; + }while (false); + + return ret; +} + +int AudioEngineImpl::play2d(const std::string &fileFullPath ,bool loop ,float volume) +{ + auto audioId = AudioEngine::INVAILD_AUDIO_ID; + + do + { + if (_engineEngine == nullptr) + break; + + auto& player = _audioPlayers[currentAudioID]; + auto initPlayer = player.init( _engineEngine, _outputMixObject, fileFullPath, volume, loop); + if (!initPlayer){ + _audioPlayers.erase(currentAudioID); + log("%s,%d message:create player for %s fail", __func__, __LINE__, fileFullPath.c_str()); + break; + } + + audioId = currentAudioID++; + player._audioID = audioId; + + (*(player._fdPlayerPlay))->RegisterCallback(player._fdPlayerPlay, PlayOverEvent, (void*)this); + (*(player._fdPlayerPlay))->SetCallbackEventsMask(player._fdPlayerPlay, SL_PLAYEVENT_HEADATEND); + + AudioEngine::_audioIDInfoMap[audioId].state = AudioEngine::AudioState::PLAYING; + } while (0); + + return audioId; +} + +void AudioEngineImpl::playerFinishCallback(SLPlayItf caller, SLuint32 playEvent) +{ + auto itend = _audioPlayers.end(); + for (auto iter = _audioPlayers.begin(); iter != itend; ++iter) + { + if (iter->second._fdPlayerPlay == caller) + { + if (iter->second._finishCallback) + { + iter->second._finishCallback(iter->second._audioID, *AudioEngine::_audioIDInfoMap[iter->second._audioID].filePath); + } + AudioEngine::stop(iter->second._audioID); + break; + } + } +} + +void AudioEngineImpl::setVolume(int audioID,float volume) +{ + auto& player = _audioPlayers[audioID]; + int dbVolume = 2000 * log10(volume); + if(dbVolume < SL_MILLIBEL_MIN){ + dbVolume = SL_MILLIBEL_MIN; + } + auto result = (*player._fdPlayerVolume)->SetVolumeLevel(player._fdPlayerVolume, dbVolume); + if(SL_RESULT_SUCCESS != result){ + log("%s error:%lu",__func__, result); + } +} + +void AudioEngineImpl::setLoop(int audioID, bool loop) +{ + auto& player = _audioPlayers[audioID]; + SLboolean loopEnabled = SL_BOOLEAN_TRUE; + if (!loop){ + loopEnabled = SL_BOOLEAN_FALSE; + } + (*player._fdPlayerSeek)->SetLoop(player._fdPlayerSeek, loopEnabled, 0, SL_TIME_UNKNOWN); +} + +void AudioEngineImpl::pause(int audioID) +{ + auto& player = _audioPlayers[audioID]; + auto result = (*player._fdPlayerPlay)->SetPlayState(player._fdPlayerPlay, SL_PLAYSTATE_PAUSED); + if(SL_RESULT_SUCCESS != result){ + log("%s error:%lu",__func__, result); + } +} + +void AudioEngineImpl::resume(int audioID) +{ + auto& player = _audioPlayers[audioID]; + auto result = (*player._fdPlayerPlay)->SetPlayState(player._fdPlayerPlay, SL_PLAYSTATE_PLAYING); + if(SL_RESULT_SUCCESS != result){ + log("%s error:%lu",__func__, result); + } +} + +void AudioEngineImpl::stop(int audioID) +{ + auto& player = _audioPlayers[audioID]; + auto result = (*player._fdPlayerPlay)->SetPlayState(player._fdPlayerPlay, SL_PLAYSTATE_STOPPED); + if(SL_RESULT_SUCCESS != result){ + log("%s error:%lu",__func__, result); + } + + _audioPlayers.erase(audioID); +} + +void AudioEngineImpl::stopAll() +{ + auto itEnd = _audioPlayers.end(); + for (auto it = _audioPlayers.begin(); it != itEnd; ++it) + { + auto result = (*it->second._fdPlayerPlay)->SetPlayState(it->second._fdPlayerPlay, SL_PLAYSTATE_STOPPED); + } + _audioPlayers.clear(); +} + +float AudioEngineImpl::getDuration(int audioID) +{ + SLmillisecond duration; + auto& player = _audioPlayers[audioID]; + auto result = (*player._fdPlayerPlay)->GetDuration(player._fdPlayerPlay, &duration); + if (duration == SL_TIME_UNKNOWN){ + return AudioEngine::TIME_UNKNOWN; + } + else{ + player._duration = duration / 1000.0; + + if (player._duration <= 0) + { + return AudioEngine::TIME_UNKNOWN; + } + + return player._duration; + } +} + +float AudioEngineImpl::getCurrentTime(int audioID) +{ + SLmillisecond currPos; + auto& player = _audioPlayers[audioID]; + (*player._fdPlayerPlay)->GetPosition(player._fdPlayerPlay, &currPos); + return currPos / 1000.0f; +} + +bool AudioEngineImpl::setCurrentTime(int audioID, float time) +{ + auto& player = _audioPlayers[audioID]; + SLmillisecond pos = 1000 * time; + auto result = (*player._fdPlayerSeek)->SetPosition(player._fdPlayerSeek, pos, SL_SEEKMODE_ACCURATE); + if(SL_RESULT_SUCCESS != result){ + return false; + } + return true; +} + +void AudioEngineImpl::setFinishCallback(int audioID, const std::function &callback) +{ + _audioPlayers[audioID]._finishCallback = callback; +} + +#endif diff --git a/cocos/audio/android/AudioEngine-inl.h b/cocos/audio/android/AudioEngine-inl.h new file mode 100644 index 0000000000..bf9f7a7773 --- /dev/null +++ b/cocos/audio/android/AudioEngine-inl.h @@ -0,0 +1,108 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID + +#ifndef __AUDIO_ENGINE_INL_H_ +#define __AUDIO_ENGINE_INL_H_ + +#include +#include +#include +#include +#include "base/ccUtils.h" + +#define MAX_AUDIOINSTANCES 24 + +#define ERRORLOG(msg) log("fun:%s,line:%d,msg:%s",__func__,__LINE__,#msg) + +NS_CC_BEGIN + +class AudioEngineImpl; + +class AudioPlayer +{ +public: + AudioPlayer(); + ~AudioPlayer(); + + bool init(SLEngineItf engineEngine, SLObjectItf outputMixObject,const std::string& fileFullPath, float volume, bool loop); + +private: + + SLObjectItf _fdPlayerObject; + SLPlayItf _fdPlayerPlay; + SLSeekItf _fdPlayerSeek; + SLVolumeItf _fdPlayerVolume; + + float _duration; + int _audioID; + + std::function _finishCallback; + + friend class AudioEngineImpl; +}; + +class AudioEngineImpl +{ +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); + void pause(int audioID); + void resume(int audioID); + void 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 &callback); + + void playerFinishCallback(SLPlayItf caller, SLuint32 playEvent); + + void uncache(const std::string& filePath){} + void uncacheAll(){} +private: + + // engine interfaces + SLObjectItf _engineObject; + SLEngineItf _engineEngine; + + // output mix interfaces + SLObjectItf _outputMixObject; + + //audioID,AudioInfo + std::unordered_map _audioPlayers; + + int currentAudioID; +}; + +#endif // __AUDIO_ENGINE_INL_H_ + +NS_CC_END + +#endif diff --git a/cocos/audio/include/AudioEngine.h b/cocos/audio/include/AudioEngine.h new file mode 100644 index 0000000000..a3663b0868 --- /dev/null +++ b/cocos/audio/include/AudioEngine.h @@ -0,0 +1,271 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS +#ifndef __AUDIO_ENGINE_H_ +#define __AUDIO_ENGINE_H_ + +#include +#include + +#include "2d/CCNode.h" +#include "Export.h" + +#ifdef ERROR +#undef ERROR +#endif // ERROR + +NS_CC_BEGIN + +class EXPORT_DLL AudioProfile +{ +public: + //name can't be empty + std::string name; + + unsigned int maxInstances; + + /* minimum delay in between sounds */ + double minDelay; + + AudioProfile() + : minDelay(0.0) + , maxInstances(0) + { + + } +}; + +class AudioEngineImpl; + +/** + @class AudioEngine + @brief + @note + */ + +class EXPORT_DLL AudioEngine +{ +public: + enum class AudioState + { + ERROR = -1, + INITIALZING, + PLAYING, + PAUSED + }; + + static const int INVAILD_AUDIO_ID; + + static const float TIME_UNKNOWN; + + static bool lazyInit(); + /** + * Release related objects + @warning It must be called before the application exit + */ + static void end(); + + /** Gets the default profile of audio instances + * @return the default profile of audio instances + */ + static AudioProfile* getDefaultProfile(); + + /** Play 2d sound + * @param filePath The path of an audio file + * @param loop Whether audio instance loop or not + * @param volume volume value (range from 0.0 to 1.0) + * @param profile a profile for audio instance + * @return an audio ID. It allows you to dynamically change the behavior of an audio instance on the fly. + */ + static int play2d(const std::string& filePath, bool loop = false, float volume = 1.0f, const AudioProfile *profile = nullptr); + + /** Sets whether an audio instance loop or not. + @param audioID an audioID returned by the play2d function + @param loop Whether audio instance loop or not + */ + static void setLoop(int audioID, bool loop); + + /** Checks whether an audio instance is loop. + * @param audioID an audioID returned by the play2d function + * @return Whether or not an audio instance is loop. + */ + static bool isLoop(int audioID); + + /** Sets volume for an audio instance. + * @param audioID an audioID returned by the play2d function + * @param volume volume value (range from 0.0 to 1.0) + */ + static void setVolume(int audioID, float volume); + + /** Gets the volume value of an audio instance. + * @param audioID an audioID returned by the play2d function + * @return volume value (range from 0.0 to 1.0) + */ + static float getVolume(int audioID); + + /** Pause an audio instance. + * @param audioID an audioID returned by the play2d function + */ + static void pause(int audioID); + + /** Pause all playing audio instances */ + static void pauseAll(); + + /** Resume an audio instance. + * @param audioID an audioID returned by the play2d function + */ + static void resume(int audioID); + + /** Resume all suspended audio instances */ + static void resumeAll(); + + /** Stop an audio instance. + * @param audioID an audioID returned by the play2d function + */ + static void stop(int audioID); + + /** Stop all audio instances */ + static void stopAll(); + + /** Sets the current playback position of an audio instance. + * @param audioID an audioID returned by the play2d function + * @return + */ + static bool setCurrentTime(int audioID, float time); + + /** Gets the current playback position of an audio instance. + * @param audioID an audioID returned by the play2d function + * @return the current playback position of an audio instance + */ + static float getCurrentTime(int audioID); + + /** Gets the duration of an audio instance. + * @param audioID an audioID returned by the play2d function + * @return the duration of an audio instance + */ + static float getDuration(int audioID); + + /** Returns the state of an audio instance. + * @param audioID an audioID returned by the play2d function + * @return the status of an audio instance + */ + static AudioState getState(int audioID); + + /** Register a callback to be invoked when an audio instance has completed playing. + * @param audioID an audioID returned by the play2d function + * @param callback + */ + static void setFinishCallback(int audioID, const std::function& callback); + + static int getMaxAudioInstance() {return _maxInstances;} + + static bool setMaxAudioInstance(int maxInstances); + + /** Uncache the audio data from internal buffer. + * AudioEngine cache audio data on ios platform + * @warning This can lead to stop related audio first. + * @param filePath The path of an audio file + */ + static void uncache(const std::string& filePath); + + /** Uncache all audio data from internal buffer. + * @warning All audio will be stopped first. + * @param + */ + static void uncacheAll(); + + /** Gets the audio profile by id of audio instance. + * @param audioID an audioID returned by the play2d function + * @return the audio profile + */ + static AudioProfile* getProfile(int audioID); + + /** Gets the audio profile by name. + * @param name name of audio profile + * @return the audio profile + */ + static AudioProfile* getProfile(const std::string &name); + +protected: + + static void remove(int audioID); + + struct ProfileHelper + { + AudioProfile profile; + + std::list audioIDs; + + double lastPlayTime; + + ProfileHelper() + : lastPlayTime(0.0) + { + + } + }; + + struct AudioInfo + { + const std::string* filePath; + ProfileHelper* profileHelper; + + float volume; + bool loop; + float duration; + AudioState state; + + bool is3dAudio; + + AudioInfo() + : profileHelper(nullptr) + , duration(TIME_UNKNOWN) + , state(AudioState::INITIALZING) + { + + } + }; + + //audioID,audioAttribute + static std::unordered_map _audioIDInfoMap; + + //audio file path,audio IDs + static std::unordered_map> _audioPathIDMap; + + //profileName,ProfileHelper + static std::unordered_map _audioPathProfileHelperMap; + + static int _maxInstances; + + static ProfileHelper* _defaultProfileHelper; + + static AudioEngineImpl* _audioEngineImpl; + + friend class AudioEngineImpl; +}; + +NS_CC_END + +#endif // __AUDIO_ENGINE_H_ +#endif diff --git a/cocos/audio/ios/AudioCache.h b/cocos/audio/ios/AudioCache.h new file mode 100644 index 0000000000..603350e507 --- /dev/null +++ b/cocos/audio/ios/AudioCache.h @@ -0,0 +1,98 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS + +#ifndef __AUDIO_CACHE_H_ +#define __AUDIO_CACHE_H_ + +#import +#import + +#include +#include +#include + +#include "CCPlatformMacros.h" + +#define QUEUEBUFFER_NUM 3 +#define QUEUEBUFFER_TIME_STEP 0.1 + +NS_CC_BEGIN + +class AudioEngineImpl; +class AudioPlayer; + +class AudioCache{ +public: + AudioCache(); + ~AudioCache(); + + void addCallbacks(const std::function &callback); + +private: + + void readDataTask(); + + void invokingCallbacks(); + + //pcm data related stuff + ALsizei _dataSize; + ALenum _format; + ALsizei _sampleRate; + float _duration; + int _bytesPerFrame; + AudioStreamBasicDescription outputFormat; + + /*Cache related stuff; + * Cache pcm data when sizeInBytes less than PCMDATA_CACHEMAXSIZE + */ + ALuint _alBufferId; + char* _pcmData; + SInt64 _bytesOfRead; + + /*Queue buffer related stuff + * Streaming in openal when sizeInBytes greater then PCMDATA_CACHEMAXSIZE + */ + char* _queBuffers[QUEUEBUFFER_NUM]; + UInt32 _queBufferFrames; + UInt32 _queBufferBytes; + + bool _alBufferReady; + std::mutex _callbackMutex; + + std::vector< std::function > _callbacks; + std::mutex _readDataTaskMutex; + + bool _exitReadDataTask; + std::string _fileFullPath; + + friend class AudioEngineImpl; + friend class AudioPlayer; +} ; + +NS_CC_END + +#endif // __AUDIO_CACHE_H_ +#endif + diff --git a/cocos/audio/ios/AudioCache.mm b/cocos/audio/ios/AudioCache.mm new file mode 100644 index 0000000000..33fae2fb40 --- /dev/null +++ b/cocos/audio/ios/AudioCache.mm @@ -0,0 +1,239 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "AudioCache.h" +#include +#import +#import + +#define PCMDATA_CACHEMAXSIZE 1048576 + +typedef ALvoid AL_APIENTRY (*alBufferDataStaticProcPtr) (const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq); +static ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq) +{ + static alBufferDataStaticProcPtr proc = NULL; + + if (proc == NULL){ + proc = (alBufferDataStaticProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alBufferDataStatic"); + } + + if (proc){ + proc(bid, format, data, size, freq); + } + + return; +} +using namespace cocos2d; + +AudioCache::AudioCache() +: _pcmData(nullptr) +, _dataSize(0) +, _bytesOfRead(0) +, _exitReadDataTask(false) +, _queBufferFrames(0) +, _queBufferBytes(0) +, _alBufferReady(false) +{ + +} + +AudioCache::~AudioCache() +{ + _exitReadDataTask = true; + if(_pcmData){ + if (_alBufferReady){ + alDeleteBuffers(1, &_alBufferId); + } + //wait for the 'readDataTask' task to exit + _readDataTaskMutex.lock(); + _readDataTaskMutex.unlock(); + + free(_pcmData); + } + + if (_queBufferFrames > 0) { + for (int index = 0; index < QUEUEBUFFER_NUM; ++index) { + free(_queBuffers[index]); + } + } +} + +void AudioCache::readDataTask() +{ + _readDataTaskMutex.lock(); + + AudioStreamBasicDescription theFileFormat; + UInt32 thePropertySize = sizeof(theFileFormat); + + SInt64 theFileLengthInFrames; + SInt64 readInFrames; + SInt64 dataSize; + SInt64 frames; + AudioBufferList theDataBuffer; + ExtAudioFileRef extRef = nullptr; + + auto fileURL = (CFURLRef)[[NSURL fileURLWithPath:[NSString stringWithCString:_fileFullPath.c_str() encoding:[NSString defaultCStringEncoding]]] retain]; + + auto error = ExtAudioFileOpenURL(fileURL, &extRef); + if(error) { + printf("%s: ExtAudioFileOpenURL FAILED, Error = %d\n", __PRETTY_FUNCTION__, error); + goto ExitThread; + } + + // Get the audio data format + error = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &theFileFormat); + if(error) { + printf("%s: ExtAudioFileGetProperty(kExtAudioFileProperty_FileDataFormat) FAILED, Error = %d\n", __PRETTY_FUNCTION__, error); + goto ExitThread; + } + if (theFileFormat.mChannelsPerFrame > 2) { + printf("%s: Unsupported Format, channel count is greater than stereo\n",__PRETTY_FUNCTION__); + goto ExitThread; + } + + // Set the client format to 16 bit signed integer (native-endian) data + // Maintain the channel count and sample rate of the original source format + outputFormat.mSampleRate = theFileFormat.mSampleRate; + outputFormat.mChannelsPerFrame = theFileFormat.mChannelsPerFrame; + + _bytesPerFrame = 2 * outputFormat.mChannelsPerFrame; + outputFormat.mFormatID = kAudioFormatLinearPCM; + outputFormat.mBytesPerPacket = _bytesPerFrame; + outputFormat.mFramesPerPacket = 1; + outputFormat.mBytesPerFrame = _bytesPerFrame; + outputFormat.mBitsPerChannel = 16; + outputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger; + + error = ExtAudioFileSetProperty(extRef, kExtAudioFileProperty_ClientDataFormat, sizeof(outputFormat), &outputFormat); + if(error) { + printf("%s: ExtAudioFileSetProperty FAILED, Error = %d\n", __PRETTY_FUNCTION__, error); + goto ExitThread; + } + + // Get the total frame count + thePropertySize = sizeof(theFileLengthInFrames); + error = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileLengthFrames, &thePropertySize, &theFileLengthInFrames); + if(error) { + printf("%s: ExtAudioFileGetProperty(kExtAudioFileProperty_FileLengthFrames) FAILED, Error = %d\n", __PRETTY_FUNCTION__, error); + goto ExitThread; + } + + _dataSize = (ALsizei)(theFileLengthInFrames * outputFormat.mBytesPerFrame); + _format = (outputFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16; + _sampleRate = (ALsizei)outputFormat.mSampleRate; + _duration = 1.0f * theFileLengthInFrames / outputFormat.mSampleRate; + + if (_dataSize <= PCMDATA_CACHEMAXSIZE) { + _pcmData = (char*)malloc(_dataSize); + alGenBuffers(1, &_alBufferId); + auto alError = alGetError(); + if (alError != AL_NO_ERROR) { + printf("%s: attaching audio to buffer fail: %x\n", __PRETTY_FUNCTION__, alError); + goto ExitThread; + } + alBufferDataStaticProc(_alBufferId, _format, _pcmData, _dataSize, _sampleRate); + + readInFrames = theFileFormat.mSampleRate * QUEUEBUFFER_TIME_STEP * QUEUEBUFFER_NUM; + dataSize = outputFormat.mBytesPerFrame * readInFrames; + if (dataSize > _dataSize) { + dataSize = _dataSize; + readInFrames = theFileLengthInFrames; + } + theDataBuffer.mNumberBuffers = 1; + theDataBuffer.mBuffers[0].mDataByteSize = (UInt32)dataSize; + theDataBuffer.mBuffers[0].mNumberChannels = outputFormat.mChannelsPerFrame; + + theDataBuffer.mBuffers[0].mData = _pcmData; + frames = readInFrames; + ExtAudioFileRead(extRef, (UInt32*)&frames, &theDataBuffer); + _alBufferReady = true; + _bytesOfRead += dataSize; + invokingCallbacks(); + + while (!_exitReadDataTask && _bytesOfRead + dataSize < _dataSize) { + theDataBuffer.mBuffers[0].mData = _pcmData + _bytesOfRead; + frames = readInFrames; + ExtAudioFileRead(extRef, (UInt32*)&frames, &theDataBuffer); + _bytesOfRead += dataSize; + } + + dataSize = _dataSize - _bytesOfRead; + if (!_exitReadDataTask && dataSize > 0) { + theDataBuffer.mBuffers[0].mDataByteSize = (UInt32)dataSize; + theDataBuffer.mBuffers[0].mData = _pcmData + _bytesOfRead; + frames = readInFrames; + ExtAudioFileRead(extRef, (UInt32*)&frames, &theDataBuffer); + } + + _bytesOfRead = _dataSize; + } + else{ + _queBufferFrames = theFileFormat.mSampleRate * QUEUEBUFFER_TIME_STEP; + _queBufferBytes = _queBufferFrames * outputFormat.mBytesPerFrame; + + theDataBuffer.mNumberBuffers = QUEUEBUFFER_NUM; + for (int index = 0; index < QUEUEBUFFER_NUM; ++index) { + _queBuffers[index] = (char*)malloc(_queBufferBytes); + + theDataBuffer.mBuffers[index].mDataByteSize = _queBufferBytes; + theDataBuffer.mBuffers[index].mNumberChannels = outputFormat.mChannelsPerFrame; + theDataBuffer.mBuffers[index].mData = _queBuffers[index]; + } + + frames = _queBufferFrames * QUEUEBUFFER_NUM; + ExtAudioFileRead(extRef, (UInt32*)&frames, &theDataBuffer); + } + +ExitThread: + CFRelease(fileURL); + if (extRef) + ExtAudioFileDispose(extRef); + + _readDataTaskMutex.unlock(); + if (_queBufferFrames > 0) + _alBufferReady = true; + + invokingCallbacks(); +} + +void AudioCache::invokingCallbacks() +{ + _callbackMutex.lock(); + auto count = _callbacks.size(); + for (size_t index = 0; index < count; ++index) { + _callbacks[index](); + } + _callbacks.clear(); + _callbackMutex.unlock(); +} + +void AudioCache::addCallbacks(const std::function &callback) +{ + _callbackMutex.lock(); + if (_alBufferReady) { + callback(); + } else { + _callbacks.push_back(callback); + } + _callbackMutex.unlock(); +} diff --git a/cocos/audio/ios/AudioEngine-inl.h b/cocos/audio/ios/AudioEngine-inl.h new file mode 100644 index 0000000000..1f67978435 --- /dev/null +++ b/cocos/audio/ios/AudioEngine-inl.h @@ -0,0 +1,94 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS + +#ifndef __AUDIO_ENGINE_INL_H_ +#define __AUDIO_ENGINE_INL_H_ + +#include + +#include "base/CCRef.h" +#include "AudioCache.h" +#include "AudioPlayer.h" + +NS_CC_BEGIN + +#define MAX_AUDIOINSTANCES 32 + +class AudioEngineThreadPool; + +class 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 &callback); + + void uncache(const std::string& filePath); + void uncacheAll(); + + void update(float dt); + +private: + void _play2d(AudioCache *cache, int audioID); + + AudioEngineThreadPool* _threadPool; + + ALuint _alSources[MAX_AUDIOINSTANCES]; + + //source,used + std::unordered_map _alSourceUsed; + + //filePath,bufferInfo + std::unordered_map _audioCaches; + + //audioID,AudioInfo + std::unordered_map _audioPlayers; + + std::mutex _threadMutex; + + std::vector _toRemoveCaches; + std::vector _toRemoveAudioIDs; + + bool _lazyInitLoop; + + int _currentAudioID; + +}; +NS_CC_END +#endif // __AUDIO_ENGINE_INL_H_ +#endif + diff --git a/cocos/audio/ios/AudioEngine-inl.mm b/cocos/audio/ios/AudioEngine-inl.mm new file mode 100644 index 0000000000..e81ade8588 --- /dev/null +++ b/cocos/audio/ios/AudioEngine-inl.mm @@ -0,0 +1,505 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "AudioEngine-inl.h" +#include "audio/include/AudioEngine.h" + +#import +#include "platform/CCFileUtils.h" +#include "base/CCDirector.h" +#include "base/CCScheduler.h" +#include "base/ccUtils.h" + +using namespace cocos2d; + +static ALCdevice *s_ALDevice = nullptr; +static ALCcontext *s_ALContext = nullptr; + +static void AudioInterrupionListenerCallback(void* user_data, UInt32 interruption_state) +{ + if(kAudioSessionBeginInterruption == interruption_state){ + alcMakeContextCurrent(nullptr); + } + else if (kAudioSessionEndInterruption == interruption_state){ + AudioSessionSetActive(true); + alcMakeContextCurrent(s_ALContext); + } +} + +namespace cocos2d { + 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 &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 _threads; + std::vector< std::function > _tasks; + + void threadFunc(int index) + { + while (_running) { + std::function task = nullptr; + _taskMutex.lock(); + task = _tasks[index]; + _taskMutex.unlock(); + + if (nullptr == task) + { + std::unique_lock 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() +{ + if (s_ALContext) { + alDeleteSources(MAX_AUDIOINSTANCES, _alSources); + + _audioCaches.clear(); + + alcDestroyContext(s_ALContext); + } + if (s_ALDevice) { + alcCloseDevice(s_ALDevice); + } + if (_threadPool) { + _threadPool->destroy(); + delete _threadPool; + } +} + +bool AudioEngineImpl::init() +{ + //set up the audio session + AudioSessionInitialize(nullptr, nullptr, AudioInterrupionListenerCallback, nullptr); + + bool ret = false; + do{ + s_ALDevice = alcOpenDevice(nullptr); + + if (s_ALDevice) { + auto alError = alGetError(); + s_ALContext = alcCreateContext(s_ALDevice, nullptr); + alcMakeContextCurrent(s_ALContext); + + alGenSources(MAX_AUDIOINSTANCES, _alSources); + alError = alGetError(); + if(alError != AL_NO_ERROR) + { + printf("%s:generating sources fail! error = %x\n", __PRETTY_FUNCTION__, alError); + break; + } + + for (int i = 0; i < MAX_AUDIOINSTANCES; ++i) { + _alSourceUsed[_alSources[i]] = false; + } + + _threadPool = new (std::nothrow) AudioEngineThreadPool(); + ret = true; + } + }while (false); + + return ret; +} + +int AudioEngineImpl::play2d(const std::string &filePath ,bool loop ,float volume) +{ + if (s_ALDevice == nullptr) { + return AudioEngine::INVAILD_AUDIO_ID; + } + + bool sourceFlag = false; + ALuint alSource = 0; + for (int i = 0; i < MAX_AUDIOINSTANCES; ++i) { + alSource = _alSources[i]; + + if ( !_alSourceUsed[alSource]) { + sourceFlag = true; + break; + } + } + if(!sourceFlag){ + return AudioEngine::INVAILD_AUDIO_ID; + } + + AudioCache* audioCache = nullptr; + auto it = _audioCaches.find(filePath); + if (it == _audioCaches.end()) { + audioCache = &_audioCaches[filePath]; + audioCache->_fileFullPath = FileUtils::getInstance()->fullPathForFilename(filePath); + + _threadPool->addTask(std::bind(&AudioCache::readDataTask, audioCache)); + } + else { + audioCache = &it->second; + } + + auto player = &_audioPlayers[_currentAudioID]; + player->_alSource = alSource; + player->_loop = loop; + player->_volume = volume; + audioCache->addCallbacks(std::bind(&AudioEngineImpl::_play2d,this,audioCache,_currentAudioID)); + + _alSourceUsed[alSource] = true; + + 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->_alBufferReady){ + 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]; + player._volume = volume; + + if (player._ready) { + alSourcef(_audioPlayers[audioID]._alSource, AL_GAIN, volume); + + auto error = alGetError(); + if (error != AL_NO_ERROR) { + printf("%s: audio id = %d, error = %x\n", __PRETTY_FUNCTION__,audioID,error); + } + } +} + +void AudioEngineImpl::setLoop(int audioID, bool loop) +{ + auto& player = _audioPlayers[audioID]; + + if (player._ready) { + if (player._streamingSource) { + player.setLoop(loop); + } else { + if (loop) { + alSourcei(player._alSource, AL_LOOPING, AL_TRUE); + } else { + alSourcei(player._alSource, AL_LOOPING, AL_FALSE); + } + + auto error = alGetError(); + if (error != AL_NO_ERROR) { + printf("%s: audio id = %d, error = %x\n", __PRETTY_FUNCTION__,audioID,error); + } + } + } + else { + player._loop = loop; + } +} + +bool AudioEngineImpl::pause(int audioID) +{ + bool ret = true; + alSourcePause(_audioPlayers[audioID]._alSource); + + auto error = alGetError(); + if (error != AL_NO_ERROR) { + ret = false; + printf("%s: audio id = %d, error = %x\n", __PRETTY_FUNCTION__,audioID,error); + } + + return ret; +} + +bool AudioEngineImpl::resume(int audioID) +{ + bool ret = true; + alSourcePlay(_audioPlayers[audioID]._alSource); + + auto error = alGetError(); + if (error != AL_NO_ERROR) { + ret = false; + printf("%s: audio id = %d, error = %x\n", __PRETTY_FUNCTION__,audioID,error); + } + + return ret; +} + +bool AudioEngineImpl::stop(int audioID) +{ + bool ret = true; + auto& player = _audioPlayers[audioID]; + if (player._ready) { + alSourceStop(player._alSource); + + auto error = alGetError(); + if (error != AL_NO_ERROR) { + ret = false; + printf("%s: audio id = %d, error = %x\n", __PRETTY_FUNCTION__,audioID,error); + } + } + + alSourcei(player._alSource, AL_BUFFER, NULL); + + _alSourceUsed[player._alSource] = false; + _audioPlayers.erase(audioID); + + return ret; +} + +void AudioEngineImpl::stopAll() +{ + for(int index = 0; index < MAX_AUDIOINSTANCES; ++index) + { + alSourceStop(_alSources[index]); + alSourcei(_alSources[index], AL_BUFFER, NULL); + _alSourceUsed[_alSources[index]] = false; + } + + _audioPlayers.clear(); +} + +float AudioEngineImpl::getDuration(int audioID) +{ + auto& player = _audioPlayers[audioID]; + if(player._ready){ + return player._audioCache->_duration; + } else { + return AudioEngine::TIME_UNKNOWN; + } +} + +float AudioEngineImpl::getCurrentTime(int audioID) +{ + float ret = 0.0f; + auto& player = _audioPlayers[audioID]; + if(player._ready){ + if (player._streamingSource) { + ret = player.getTime(); + } else { + alGetSourcef(player._alSource, AL_SEC_OFFSET, &ret); + + auto error = alGetError(); + if (error != AL_NO_ERROR) { + printf("%s, audio id:%d,error code:%x", __PRETTY_FUNCTION__,audioID,error); + } + } + } + + return ret; +} + +bool AudioEngineImpl::setCurrentTime(int audioID, float time) +{ + bool ret = false; + auto& player = _audioPlayers[audioID]; + + do { + if (!player._ready) { + break; + } + + if (player._streamingSource) { + ret = player.setTime(time); + break; + } + else { + if (player._audioCache->_bytesOfRead != player._audioCache->_dataSize && + (time * player._audioCache->_sampleRate * player._audioCache->_bytesPerFrame) > player._audioCache->_bytesOfRead) { + printf("%s: audio id = %d\n", __PRETTY_FUNCTION__,audioID); + break; + } + + alSourcef(player._alSource, AL_SEC_OFFSET, time); + + auto error = alGetError(); + if (error != AL_NO_ERROR) { + printf("%s: audio id = %d, error = %x\n", __PRETTY_FUNCTION__,audioID,error); + } + ret = true; + } + } while (0); + + return ret; +} + +void AudioEngineImpl::setFinishCallback(int audioID, const std::function &callback) +{ + _audioPlayers[audioID]._finishCallbak = callback; +} + +void AudioEngineImpl::update(float dt) +{ + ALint sourceState; + 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()) { + _alSourceUsed[playerIt->second._alSource] = false; + _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; + alGetSourcei(player._alSource, AL_SOURCE_STATE, &sourceState); + + if (player._ready && sourceState == AL_STOPPED) { + _alSourceUsed[player._alSource] = false; + auto& audioInfo = AudioEngine::_audioIDInfoMap[audioID]; + if (player._finishCallbak) { + player._finishCallbak(audioID, *audioInfo.filePath); + } + + AudioEngine::remove(audioID); + + it = _audioPlayers.erase(it); + } + else{ + ++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) +{ + auto fileFullPath = FileUtils::getInstance()->fullPathForFilename(filePath); + _audioCaches.erase(fileFullPath); +} + +void AudioEngineImpl::uncacheAll() +{ + _audioCaches.clear(); +} diff --git a/cocos/audio/ios/AudioPlayer.h b/cocos/audio/ios/AudioPlayer.h new file mode 100644 index 0000000000..76d9e3ad31 --- /dev/null +++ b/cocos/audio/ios/AudioPlayer.h @@ -0,0 +1,76 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS + +#ifndef __AUDIO_PLAYER_H_ +#define __AUDIO_PLAYER_H_ + +#import +#include +#include +#include "CCPlatformMacros.h" + +NS_CC_BEGIN +class AudioCache; +class AudioEngineImpl; + +class AudioPlayer +{ +public: + AudioPlayer(); + ~AudioPlayer(); + + //queue buffer related stuff + bool setTime(float time); + float getTime() { return _currTime;} + bool setLoop(bool loop); + +private: + void rotateBufferThread(int offsetFrame); + bool play2d(AudioCache* cache); + + AudioCache* _audioCache; + + float _volume; + bool _loop; + std::function _finishCallbak; + + bool _ready; + ALuint _alSource; + + //play by circular buffer + float _currTime; + bool _streamingSource; + ALuint _bufferIds[3]; + std::thread _rotateBufferThread; + std::timed_mutex _timeMtx; + bool _exitThread; + bool _timeDirty; + + friend class AudioEngineImpl; +}; +NS_CC_END +#endif // __AUDIO_PLAYER_H_ +#endif + diff --git a/cocos/audio/ios/AudioPlayer.mm b/cocos/audio/ios/AudioPlayer.mm new file mode 100644 index 0000000000..c7d93216d4 --- /dev/null +++ b/cocos/audio/ios/AudioPlayer.mm @@ -0,0 +1,214 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "AudioPlayer.h" +#include "AudioCache.h" +#include "platform/CCFileUtils.h" +#import + +using namespace cocos2d; + +AudioPlayer::AudioPlayer() +: _exitThread(false) +, _timeDirty(false) +, _streamingSource(false) +, _currTime(0.0f) +, _finishCallbak(nullptr) +, _ready(false) +, _audioCache(nullptr) +{ + +} + +AudioPlayer::~AudioPlayer() +{ + _exitThread = true; + if (_audioCache && _audioCache->_queBufferFrames > 0) { + _timeMtx.unlock(); + if (_rotateBufferThread.joinable()) { + _rotateBufferThread.join(); + } + alDeleteBuffers(3, _bufferIds); + } +} + +bool AudioPlayer::play2d(AudioCache* cache) +{ + if (!cache->_alBufferReady) { + return false; + } + _audioCache = cache; + + alSourcei(_alSource, AL_BUFFER, NULL); + alSourcef(_alSource, AL_PITCH, 1.0f); + alSourcef(_alSource, AL_GAIN, _volume); + + if (_audioCache->_queBufferFrames == 0) { + if (_loop) { + alSourcei(_alSource, AL_LOOPING, AL_TRUE); + } + else { + alSourcei(_alSource, AL_LOOPING, AL_FALSE); + } + alSourcei(_alSource, AL_BUFFER, _audioCache->_alBufferId); + + } else { + _streamingSource = true; + + auto alError = alGetError(); + alGenBuffers(3, _bufferIds); + alError = alGetError(); + if (alError == AL_NO_ERROR) { + for (int index = 0; index < QUEUEBUFFER_NUM; ++index) { + alBufferData(_bufferIds[index], _audioCache->_format, _audioCache->_queBuffers[index], _audioCache->_queBufferBytes, _audioCache->_sampleRate); + } + alSourcei(_alSource, AL_BUFFER, NULL); + alSourceQueueBuffers(_alSource, QUEUEBUFFER_NUM, _bufferIds); + + _timeMtx.lock(); + _rotateBufferThread = std::thread(&AudioPlayer::rotateBufferThread,this, _audioCache->_queBufferFrames * QUEUEBUFFER_NUM + 1); + } + else { + printf("%s:alGenBuffers error code:%x", __PRETTY_FUNCTION__,alError); + return false; + } + } + + alSourcePlay(_alSource); + _ready = true; + auto alError = alGetError(); + + if (alError != AL_NO_ERROR) { + printf("%s:alSourcePlay error code:%x\n", __PRETTY_FUNCTION__,alError); + return false; + } + + return true; +} + +void AudioPlayer::rotateBufferThread(int offsetFrame) +{ + printf("%s start\n",__PRETTY_FUNCTION__); + + ALint sourceState; + ALint bufferProcessed = 0; + ExtAudioFileRef extRef = nullptr; + + auto fileURL = (CFURLRef)[[NSURL fileURLWithPath:[NSString stringWithCString:_audioCache->_fileFullPath.c_str() encoding:[NSString defaultCStringEncoding]]] retain]; + char* tmpBuffer = (char*)malloc(_audioCache->_queBufferBytes); + auto frames = _audioCache->_queBufferFrames; + + auto error = ExtAudioFileOpenURL(fileURL, &extRef); + if(error) { + printf("%s: ExtAudioFileOpenURL FAILED, Error = %d\n", __PRETTY_FUNCTION__, error); + goto ExitBufferThread; + } + + error = ExtAudioFileSetProperty(extRef, kExtAudioFileProperty_ClientDataFormat, sizeof(_audioCache->outputFormat), &_audioCache->outputFormat); + AudioBufferList theDataBuffer; + theDataBuffer.mNumberBuffers = 1; + theDataBuffer.mBuffers[0].mData = tmpBuffer; + theDataBuffer.mBuffers[0].mDataByteSize = _audioCache->_queBufferBytes; + theDataBuffer.mBuffers[0].mNumberChannels = _audioCache->outputFormat.mChannelsPerFrame; + + if (offsetFrame != 0) { + ExtAudioFileSeek(extRef, offsetFrame); + } + + while (!_exitThread) { + alGetSourcei(_alSource, AL_SOURCE_STATE, &sourceState); + if (sourceState == AL_PLAYING) { + alGetSourcei(_alSource, AL_BUFFERS_PROCESSED, &bufferProcessed); + while (bufferProcessed > 0) { + bufferProcessed--; + if (_timeDirty) { + _timeDirty = false; + offsetFrame = _currTime * _audioCache->outputFormat.mSampleRate; + ExtAudioFileSeek(extRef, offsetFrame); + } + else { + _currTime += QUEUEBUFFER_TIME_STEP; + if (_currTime > _audioCache->_duration) { + if (_loop) { + _currTime = 0.0f; + } else { + _currTime = _audioCache->_duration; + } + } + } + + frames = _audioCache->_queBufferFrames; + ExtAudioFileRead(extRef, (UInt32*)&frames, &theDataBuffer); + if (frames <= 0) { + if (_loop) { + ExtAudioFileSeek(extRef, 0); + frames = _audioCache->_queBufferFrames; + theDataBuffer.mBuffers[0].mDataByteSize = _audioCache->_queBufferBytes; + ExtAudioFileRead(extRef, (UInt32*)&frames, &theDataBuffer); + } else { + _exitThread = true; + break; + } + } + + ALuint bid; + alSourceUnqueueBuffers(_alSource, 1, &bid); + alBufferData(bid, _audioCache->_format, tmpBuffer, frames * _audioCache->outputFormat.mBytesPerFrame, _audioCache->_sampleRate); + alSourceQueueBuffers(_alSource, 1, &bid); + } + } + + _timeMtx.try_lock_for(std::chrono::milliseconds(50)); + } + +ExitBufferThread: + CFRelease(fileURL); + // Dispose the ExtAudioFileRef, it is no longer needed + if (extRef){ + ExtAudioFileDispose(extRef); + } + free(tmpBuffer); + printf("%s: end\n",__PRETTY_FUNCTION__); +} + +bool AudioPlayer::setLoop(bool loop) +{ + if (!_exitThread ) { + _loop = loop; + return true; + } + + return false; +} + +bool AudioPlayer::setTime(float time) +{ + if (!_exitThread && time >= 0.0f && time < _audioCache->_duration) { + + _currTime = time; + _timeDirty = true; + + return true; + } + return false; +} diff --git a/cocos/base/CCDirector.cpp b/cocos/base/CCDirector.cpp index 3c28800afd..a0b5692e69 100644 --- a/cocos/base/CCDirector.cpp +++ b/cocos/base/CCDirector.cpp @@ -284,6 +284,9 @@ void Director::drawScene() if (_runningScene) { + //clear draw stats + _renderer->clearDrawStats(); + Camera* defaultCamera = nullptr; const auto& cameras = _runningScene->_cameras; //draw with camera diff --git a/cocos/base/CCUserDefault-apple.mm b/cocos/base/CCUserDefault-apple.mm index 0f004e200c..d5a1bec96d 100644 --- a/cocos/base/CCUserDefault-apple.mm +++ b/cocos/base/CCUserDefault-apple.mm @@ -32,8 +32,8 @@ #import "CCUserDefault.h" #import "tinyxml2.h" -#import "CCPlatformConfig.h" -#import "CCPlatformMacros.h" +#import "platform/CCPlatformConfig.h" +#import "platform/CCPlatformMacros.h" #import "base64.h" #import "platform/CCFileUtils.h" diff --git a/cocos/cocos2d.h b/cocos/cocos2d.h index f240c4f7e8..e322b14a0d 100644 --- a/cocos/cocos2d.h +++ b/cocos/cocos2d.h @@ -280,6 +280,7 @@ THE SOFTWARE. #include "3d/CCAttachNode.h" #include "3d/CCMeshVertexIndexData.h" #include "3d/CCSkeleton3D.h" +#include "3d/CCBillBoard.h" // Deprecated include #include "deprecated/CCDictionary.h" diff --git a/cocos/editor-support/cocostudio/CCArmature.cpp b/cocos/editor-support/cocostudio/CCArmature.cpp index a005e23127..62517e1604 100644 --- a/cocos/editor-support/cocostudio/CCArmature.cpp +++ b/cocos/editor-support/cocostudio/CCArmature.cpp @@ -486,8 +486,9 @@ void Armature::visit(cocos2d::Renderer *renderer, const Mat4 &parentTransform, u sortAllChildren(); draw(renderer, _modelViewTransform, flags); - // reset for next frame - _orderOfArrival = 0; + // FIX ME: Why need to set _orderOfArrival to 0?? + // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920 + // setOrderOfArrival(0); director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); } diff --git a/cocos/editor-support/cocostudio/CCBatchNode.cpp b/cocos/editor-support/cocostudio/CCBatchNode.cpp index c8128748f3..19d339d6c7 100644 --- a/cocos/editor-support/cocostudio/CCBatchNode.cpp +++ b/cocos/editor-support/cocostudio/CCBatchNode.cpp @@ -124,8 +124,9 @@ void BatchNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t sortAllChildren(); draw(renderer, _modelViewTransform, flags); - // reset for next frame - _orderOfArrival = 0; + // FIX ME: Why need to set _orderOfArrival to 0?? + // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920 + // setOrderOfArrival(0); director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); } diff --git a/cocos/math/Mat4.cpp b/cocos/math/Mat4.cpp index ff598d3da8..1e3dc5a972 100644 --- a/cocos/math/Mat4.cpp +++ b/cocos/math/Mat4.cpp @@ -414,8 +414,11 @@ void Mat4::add(float scalar) void Mat4::add(float scalar, Mat4* dst) { GP_ASSERT(dst); - +#ifdef __SSE__ + MathUtil::addMatrix(col, scalar, dst->col); +#else MathUtil::addMatrix(m, scalar, dst->m); +#endif } void Mat4::add(const Mat4& mat) @@ -426,8 +429,11 @@ void Mat4::add(const Mat4& mat) void Mat4::add(const Mat4& m1, const Mat4& m2, Mat4* dst) { GP_ASSERT(dst); - +#ifdef __SSE__ + MathUtil::addMatrix(m1.col, m2.col, dst->col); +#else MathUtil::addMatrix(m1.m, m2.m, dst->m); +#endif } bool Mat4::decompose(Vec3* scale, Quaternion* rotation, Vec3* translation) const @@ -700,8 +706,11 @@ void Mat4::multiply(float scalar, Mat4* dst) const void Mat4::multiply(const Mat4& m, float scalar, Mat4* dst) { GP_ASSERT(dst); - +#ifdef __SSE__ + MathUtil::multiplyMatrix(m.col, scalar, dst->col); +#else MathUtil::multiplyMatrix(m.m, scalar, dst->m); +#endif } void Mat4::multiply(const Mat4& mat) @@ -712,13 +721,20 @@ void Mat4::multiply(const Mat4& mat) void Mat4::multiply(const Mat4& m1, const Mat4& m2, Mat4* dst) { GP_ASSERT(dst); - +#ifdef __SSE__ + MathUtil::multiplyMatrix(m1.col, m2.col, dst->col); +#else MathUtil::multiplyMatrix(m1.m, m2.m, dst->m); +#endif } void Mat4::negate() { +#ifdef __SSE__ + MathUtil::negateMatrix(col, col); +#else MathUtil::negateMatrix(m, m); +#endif } Mat4 Mat4::getNegated() const @@ -870,8 +886,11 @@ void Mat4::subtract(const Mat4& mat) void Mat4::subtract(const Mat4& m1, const Mat4& m2, Mat4* dst) { GP_ASSERT(dst); - +#ifdef __SSE__ + MathUtil::subtractMatrix(m1.col, m2.col, dst->col); +#else MathUtil::subtractMatrix(m1.m, m2.m, dst->m); +#endif } void Mat4::transformPoint(Vec3* point) const @@ -912,8 +931,11 @@ void Mat4::transformVector(Vec4* vector) const void Mat4::transformVector(const Vec4& vector, Vec4* dst) const { GP_ASSERT(dst); - +#ifdef __SSE__ + MathUtil::transformVec4(col, vector.v, dst->v); +#else MathUtil::transformVec4(m, (const float*) &vector, (float*)dst); +#endif } void Mat4::translate(float x, float y, float z) @@ -940,7 +962,11 @@ void Mat4::translate(const Vec3& t, Mat4* dst) const void Mat4::transpose() { +#ifdef __SSE__ + MathUtil::transposeMatrix(col, col); +#else MathUtil::transposeMatrix(m, m); +#endif } Mat4 Mat4::getTransposed() const diff --git a/cocos/math/Mat4.h b/cocos/math/Mat4.h index 53b4b64da1..7616221943 100644 --- a/cocos/math/Mat4.h +++ b/cocos/math/Mat4.h @@ -24,6 +24,10 @@ #include "math/Vec3.h" #include "math/Vec4.h" +#ifdef __SSE__ +#include +#endif + NS_CC_MATH_BEGIN //class Plane; @@ -77,7 +81,14 @@ public: /** * Stores the columns of this 4x4 matrix. * */ +#ifdef __SSE__ + union { + __m128 col[4]; + float m[16]; + }; +#else float m[16]; +#endif /** * Constructs a matrix initialized to the identity matrix: diff --git a/cocos/math/MathUtil.h b/cocos/math/MathUtil.h index da5fe3c830..acf6ab0b42 100644 --- a/cocos/math/MathUtil.h +++ b/cocos/math/MathUtil.h @@ -21,6 +21,10 @@ #ifndef MATHUTIL_H_ #define MATHUTIL_H_ +#ifdef __SSE__ +#include +#endif + #include "CCMathBase.h" NS_CC_MATH_BEGIN @@ -67,7 +71,23 @@ public: static void smooth(float* x, float target, float elapsedTime, float riseTime, float fallTime); private: - +#ifdef __SSE__ + inline static void addMatrix(const __m128 m[4], float scalar, __m128 dst[4]); + + inline static void addMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4]); + + inline static void subtractMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4]); + + inline static void multiplyMatrix(const __m128 m[4], float scalar, __m128 dst[4]); + + inline static void multiplyMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4]); + + inline static void negateMatrix(const __m128 m[4], __m128 dst[4]); + + inline static void transposeMatrix(const __m128 m[4], __m128 dst[4]); + + inline static void transformVec4(const __m128 m[4], const __m128& v, __m128& dst); +#endif inline static void addMatrix(const float* m, float scalar, float* dst); inline static void addMatrix(const float* m1, const float* m2, float* dst); @@ -99,6 +119,9 @@ NS_CC_MATH_END #include "MathUtilNeon.inl" #else #include "MathUtil.inl" +#if defined(__SSE__) +#include "MathUtilSSE.inl" +#endif #endif #endif diff --git a/cocos/math/MathUtilSSE.inl b/cocos/math/MathUtilSSE.inl new file mode 100644 index 0000000000..b701bb51ca --- /dev/null +++ b/cocos/math/MathUtilSSE.inl @@ -0,0 +1,152 @@ +NS_CC_MATH_BEGIN + +inline void MathUtil::addMatrix(const __m128 m[4], float scalar, __m128 dst[4]) +{ + __m128 s = _mm_set1_ps(scalar); + dst[0] = _mm_add_ps(m[0], s); + dst[1] = _mm_add_ps(m[1], s); + dst[2] = _mm_add_ps(m[2], s); + dst[3] = _mm_add_ps(m[3], s); +} + +inline void MathUtil::addMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4]) +{ + dst[0] = _mm_add_ps(m1[0], m2[0]); + dst[1] = _mm_add_ps(m1[1], m2[1]); + dst[2] = _mm_add_ps(m1[2], m2[2]); + dst[3] = _mm_add_ps(m1[3], m2[3]); +} + +inline void MathUtil::subtractMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4]) +{ + dst[0] = _mm_sub_ps(m1[0], m2[0]); + dst[1] = _mm_sub_ps(m1[1], m2[1]); + dst[2] = _mm_sub_ps(m1[2], m2[2]); + dst[3] = _mm_sub_ps(m1[3], m2[3]); +} + +inline void MathUtil::multiplyMatrix(const __m128 m[4], float scalar, __m128 dst[4]) +{ + __m128 s = _mm_set1_ps(scalar); + dst[0] = _mm_mul_ps(m[0], s); + dst[1] = _mm_mul_ps(m[1], s); + dst[2] = _mm_mul_ps(m[2], s); + dst[3] = _mm_mul_ps(m[3], s); +} + +inline void MathUtil::multiplyMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4]) +{ + __m128 dst0, dst1, dst2, dst3; + { + __m128 e0 = _mm_shuffle_ps(m2[0], m2[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(m2[0], m2[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(m2[0], m2[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(m2[0], m2[0], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 v0 = _mm_mul_ps(m1[0], e0); + __m128 v1 = _mm_mul_ps(m1[1], e1); + __m128 v2 = _mm_mul_ps(m1[2], e2); + __m128 v3 = _mm_mul_ps(m1[3], e3); + + __m128 a0 = _mm_add_ps(v0, v1); + __m128 a1 = _mm_add_ps(v2, v3); + __m128 a2 = _mm_add_ps(a0, a1); + + dst0 = a2; + } + + { + __m128 e0 = _mm_shuffle_ps(m2[1], m2[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(m2[1], m2[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(m2[1], m2[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(m2[1], m2[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 v0 = _mm_mul_ps(m1[0], e0); + __m128 v1 = _mm_mul_ps(m1[1], e1); + __m128 v2 = _mm_mul_ps(m1[2], e2); + __m128 v3 = _mm_mul_ps(m1[3], e3); + + __m128 a0 = _mm_add_ps(v0, v1); + __m128 a1 = _mm_add_ps(v2, v3); + __m128 a2 = _mm_add_ps(a0, a1); + + dst1 = a2; + } + + { + __m128 e0 = _mm_shuffle_ps(m2[2], m2[2], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(m2[2], m2[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(m2[2], m2[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(m2[2], m2[2], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 v0 = _mm_mul_ps(m1[0], e0); + __m128 v1 = _mm_mul_ps(m1[1], e1); + __m128 v2 = _mm_mul_ps(m1[2], e2); + __m128 v3 = _mm_mul_ps(m1[3], e3); + + __m128 a0 = _mm_add_ps(v0, v1); + __m128 a1 = _mm_add_ps(v2, v3); + __m128 a2 = _mm_add_ps(a0, a1); + + dst2 = a2; + } + + { + __m128 e0 = _mm_shuffle_ps(m2[3], m2[3], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(m2[3], m2[3], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(m2[3], m2[3], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(m2[3], m2[3], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 v0 = _mm_mul_ps(m1[0], e0); + __m128 v1 = _mm_mul_ps(m1[1], e1); + __m128 v2 = _mm_mul_ps(m1[2], e2); + __m128 v3 = _mm_mul_ps(m1[3], e3); + + __m128 a0 = _mm_add_ps(v0, v1); + __m128 a1 = _mm_add_ps(v2, v3); + __m128 a2 = _mm_add_ps(a0, a1); + + dst3 = a2; + } + dst[0] = dst0; + dst[1] = dst1; + dst[2] = dst2; + dst[3] = dst3; +} + +inline void MathUtil::negateMatrix(const __m128 m[4], __m128 dst[4]) +{ + __m128 z = _mm_setzero_ps(); + dst[0] = _mm_sub_ps(z, m[0]); + dst[1] = _mm_sub_ps(z, m[1]); + dst[2] = _mm_sub_ps(z, m[2]); + dst[3] = _mm_sub_ps(z, m[3]); +} + +inline void MathUtil::transposeMatrix(const __m128 m[4], __m128 dst[4]) +{ + __m128 tmp0 = _mm_shuffle_ps(m[0], m[1], 0x44); + __m128 tmp2 = _mm_shuffle_ps(m[0], m[1], 0xEE); + __m128 tmp1 = _mm_shuffle_ps(m[2], m[3], 0x44); + __m128 tmp3 = _mm_shuffle_ps(m[2], m[3], 0xEE); + + dst[0] = _mm_shuffle_ps(tmp0, tmp1, 0x88); + dst[1] = _mm_shuffle_ps(tmp0, tmp1, 0xDD); + dst[2] = _mm_shuffle_ps(tmp2, tmp3, 0x88); + dst[3] = _mm_shuffle_ps(tmp2, tmp3, 0xDD); +} + +inline void MathUtil::transformVec4(const __m128 m[4], const __m128& v, __m128& dst) +{ + __m128 col1 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 col2 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 col3 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 col4 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(3, 3, 3, 3)); + + dst = _mm_add_ps( + _mm_add_ps(_mm_mul_ps(m[0], col1), _mm_mul_ps(m[1], col2)), + _mm_add_ps(_mm_mul_ps(m[2], col3), _mm_mul_ps(m[3], col4)) + ); +} + +NS_CC_MATH_END diff --git a/cocos/math/Vec4.h b/cocos/math/Vec4.h index d6399fb339..712f60fd4f 100644 --- a/cocos/math/Vec4.h +++ b/cocos/math/Vec4.h @@ -21,6 +21,10 @@ #ifndef MATH_VEC4_H #define MATH_VEC4_H +#ifdef __SSE__ +#include +#endif + #include "math/CCMathBase.h" NS_CC_MATH_BEGIN @@ -33,7 +37,17 @@ class Mat4; class CC_DLL Vec4 { public: - +#ifdef __SSE__ + union { + struct { + float x; + float y; + float z; + float w; + }; + __m128 v; + }; +#else /** * The x-coordinate. */ @@ -53,7 +67,7 @@ public: * The w-coordinate. */ float w; - +#endif /** * Constructs a new vector initialized to all zeros. */ diff --git a/cocos/platform/mac/CCApplication-mac.mm b/cocos/platform/mac/CCApplication-mac.mm index 3f7f1d4f1c..ca72c23883 100644 --- a/cocos/platform/mac/CCApplication-mac.mm +++ b/cocos/platform/mac/CCApplication-mac.mm @@ -26,11 +26,10 @@ THE SOFTWARE. #include "platform/CCPlatformConfig.h" #if CC_TARGET_PLATFORM == CC_PLATFORM_MAC -#import "CCApplication.h" - #import #include +#import "platform/CCApplication.h" #include "platform/CCFileUtils.h" #include "math/CCGeometry.h" #include "base/CCDirector.h" diff --git a/cocos/renderer/CCRenderer.cpp b/cocos/renderer/CCRenderer.cpp index 59f39482b6..e62c812e05 100644 --- a/cocos/renderer/CCRenderer.cpp +++ b/cocos/renderer/CCRenderer.cpp @@ -102,6 +102,32 @@ void RenderQueue::clear() _queuePosZ.clear(); } +// helper +static bool compareTransparentRenderCommand(RenderCommand* a, RenderCommand* b) +{ + return a->getGlobalOrder() > b->getGlobalOrder(); +} + +void TransparentRenderQueue::push_back(RenderCommand* command) +{ + _queueCmd.push_back(command); +} + +void TransparentRenderQueue::sort() +{ + std::sort(std::begin(_queueCmd), std::end(_queueCmd), compareTransparentRenderCommand); +} + +RenderCommand* TransparentRenderQueue::operator[](ssize_t index) const +{ + return _queueCmd[index]; +} + +void TransparentRenderQueue::clear() +{ + _queueCmd.clear(); +} + // // // @@ -245,6 +271,11 @@ void Renderer::addCommand(RenderCommand* command, int renderQueue) _renderGroups[renderQueue].push_back(command); } +void Renderer::addCommandToTransparentQueue(RenderCommand* command) +{ + _transparentRenderGroups.push_back(command); +} + void Renderer::pushGroup(int renderQueueID) { CCASSERT(!_isRendering, "Cannot change render queue while rendering"); @@ -337,6 +368,58 @@ void Renderer::visitRenderQueue(const RenderQueue& queue) } } +void Renderer::visitTransparentRenderQueue(const TransparentRenderQueue& queue) +{ + // do not batch for transparent objects + ssize_t size = queue.size(); + + _batchedCommands.clear(); + _filledVertex = 0; + _filledIndex = 0; + + for (ssize_t index = 0; index < size; ++index) + { + auto command = queue[index]; + auto commandType = command->getType(); + if(RenderCommand::Type::QUAD_COMMAND == commandType || RenderCommand::Type::TRIANGLES_COMMAND == commandType) + { + auto cmd = static_cast(command); + _batchedCommands.push_back(cmd); + fillVerticesAndIndices(cmd); + drawBatchedQuads(); + } + else if(RenderCommand::Type::GROUP_COMMAND == commandType) + { + int renderQueueID = (static_cast(command))->getRenderQueueID(); + visitRenderQueue(_renderGroups[renderQueueID]); + } + else if(RenderCommand::Type::CUSTOM_COMMAND == commandType) + { + auto cmd = static_cast(command); + cmd->execute(); + } + else if(RenderCommand::Type::BATCH_COMMAND == commandType) + { + auto cmd = static_cast(command); + cmd->execute(); + } + else if(RenderCommand::Type::PRIMITIVE_COMMAND == commandType) + { + auto cmd = static_cast(command); + cmd->execute(); + } + else if (RenderCommand::Type::MESH_COMMAND == commandType) + { + auto cmd = static_cast(command); + cmd->execute(); + } + else + { + CCLOGERROR("Unknown commands in renderQueue"); + } + } +} + void Renderer::render() { //Uncomment this once everything is rendered by new renderer @@ -347,9 +430,6 @@ void Renderer::render() if (_glViewAssigned) { - // cleanup - _drawnBatches = _drawnVertices = 0; - //Process render commands //1. Sort render commands based on ID for (auto &renderqueue : _renderGroups) @@ -358,6 +438,16 @@ void Renderer::render() } visitRenderQueue(_renderGroups[0]); flush(); + + //Process render commands + //draw transparent objects here, do not batch for transparent objects + if (0 < _transparentRenderGroups.size()) + { + _transparentRenderGroups.sort(); + glEnable(GL_DEPTH_TEST); + visitTransparentRenderQueue(_transparentRenderGroups); + glDisable(GL_DEPTH_TEST); + } } clean(); _isRendering = false; @@ -382,6 +472,8 @@ void Renderer::clean() _filledIndex = 0; _lastMaterialID = 0; _lastBatchedMeshCommand = nullptr; + + _transparentRenderGroups.clear(); } void Renderer::fillVerticesAndIndices(const TrianglesCommand* cmd) diff --git a/cocos/renderer/CCRenderer.h b/cocos/renderer/CCRenderer.h index 9402fa15a7..a2f21966c2 100644 --- a/cocos/renderer/CCRenderer.h +++ b/cocos/renderer/CCRenderer.h @@ -61,6 +61,22 @@ protected: std::vector _queuePosZ; }; +//render queue for transparency object, NOTE that the _globalOrder of RenderCommand is the distance to the camera when added to the transparent queue +class TransparentRenderQueue { +public: + void push_back(RenderCommand* command); + ssize_t size() const + { + return _queueCmd.size(); + } + void sort(); + RenderCommand* operator[](ssize_t index) const; + void clear(); + +protected: + std::vector _queueCmd; +}; + struct RenderStackElement { int renderQueueID; @@ -92,6 +108,9 @@ public: /** Adds a `RenderComamnd` into the renderer specifying a particular render queue ID */ void addCommand(RenderCommand* command, int renderQueue); + + /** add transprent command */ + void addCommandToTransparentQueue(RenderCommand* command); /** Pushes a group into the render queue */ void pushGroup(int renderQueueID); @@ -116,6 +135,8 @@ public: ssize_t getDrawnVertices() const { return _drawnVertices; } /* RenderCommands (except) QuadCommand should update this value */ void addDrawnVertices(ssize_t number) { _drawnVertices += number; }; + /* clear draw stats */ + void clearDrawStats() { _drawnBatches = _drawnVertices = 0; } inline GroupCommandManager* getGroupCommandManager() const { return _groupCommandManager; }; @@ -140,12 +161,15 @@ protected: void flush3D(); void visitRenderQueue(const RenderQueue& queue); + + void visitTransparentRenderQueue(const TransparentRenderQueue& queue); void fillVerticesAndIndices(const TrianglesCommand* cmd); std::stack _commandGroupStack; std::vector _renderGroups; + TransparentRenderQueue _transparentRenderGroups; //transparency objects uint32_t _lastMaterialID; diff --git a/cocos/scripting/lua-bindings/auto/lua_cocos2dx_extension_auto.cpp b/cocos/scripting/lua-bindings/auto/lua_cocos2dx_extension_auto.cpp index 6958a28aa3..1f1c29dacd 100644 --- a/cocos/scripting/lua-bindings/auto/lua_cocos2dx_extension_auto.cpp +++ b/cocos/scripting/lua-bindings/auto/lua_cocos2dx_extension_auto.cpp @@ -8511,6 +8511,50 @@ int lua_cocos2dx_extension_ScrollView_setMaxScale(lua_State* tolua_S) return 0; } +int lua_cocos2dx_extension_ScrollView_hasVisibleParents(lua_State* tolua_S) +{ + int argc = 0; + cocos2d::extension::ScrollView* cobj = nullptr; + bool ok = true; + +#if COCOS2D_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if COCOS2D_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"cc.ScrollView",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (cocos2d::extension::ScrollView*)tolua_tousertype(tolua_S,1,0); + +#if COCOS2D_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_extension_ScrollView_hasVisibleParents'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + return 0; + bool ret = cobj->hasVisibleParents(); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + CCLOG("%s has wrong number of arguments: %d, was expecting %d \n", "cc.ScrollView:hasVisibleParents",argc, 0); + return 0; + +#if COCOS2D_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_extension_ScrollView_hasVisibleParents'.",&tolua_err); +#endif + + return 0; +} int lua_cocos2dx_extension_ScrollView_getDirection(lua_State* tolua_S) { int argc = 0; @@ -9937,6 +9981,7 @@ int lua_register_cocos2dx_extension_ScrollView(lua_State* tolua_S) tolua_function(tolua_S,"setZoomScaleInDuration",lua_cocos2dx_extension_ScrollView_setZoomScaleInDuration); tolua_function(tolua_S,"updateTweenAction",lua_cocos2dx_extension_ScrollView_updateTweenAction); tolua_function(tolua_S,"setMaxScale",lua_cocos2dx_extension_ScrollView_setMaxScale); + tolua_function(tolua_S,"hasVisibleParents",lua_cocos2dx_extension_ScrollView_hasVisibleParents); tolua_function(tolua_S,"getDirection",lua_cocos2dx_extension_ScrollView_getDirection); tolua_function(tolua_S,"getContainer",lua_cocos2dx_extension_ScrollView_getContainer); tolua_function(tolua_S,"setMinScale",lua_cocos2dx_extension_ScrollView_setMinScale); diff --git a/cocos/scripting/lua-bindings/auto/lua_cocos2dx_extension_auto.hpp b/cocos/scripting/lua-bindings/auto/lua_cocos2dx_extension_auto.hpp index cbd41e6a6b..483cbe013a 100644 --- a/cocos/scripting/lua-bindings/auto/lua_cocos2dx_extension_auto.hpp +++ b/cocos/scripting/lua-bindings/auto/lua_cocos2dx_extension_auto.hpp @@ -262,6 +262,7 @@ int register_all_cocos2dx_extension(lua_State* tolua_S); + #endif // __cocos2dx_extension_h__ diff --git a/cocos/scripting/lua-bindings/proj.ios_mac/cocos2d_lua_bindings.xcodeproj/project.pbxproj b/cocos/scripting/lua-bindings/proj.ios_mac/cocos2d_lua_bindings.xcodeproj/project.pbxproj index 260b98b268..05f642556d 100644 --- a/cocos/scripting/lua-bindings/proj.ios_mac/cocos2d_lua_bindings.xcodeproj/project.pbxproj +++ b/cocos/scripting/lua-bindings/proj.ios_mac/cocos2d_lua_bindings.xcodeproj/project.pbxproj @@ -871,7 +871,7 @@ 1551A336158F2AB200E66CFE /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0510; + LastUpgradeCheck = 0600; ORGANIZATIONNAME = ""; }; buildConfigurationList = 1551A339158F2AB200E66CFE /* Build configuration list for PBXProject "cocos2d_lua_bindings" */; @@ -1107,7 +1107,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COMBINE_HIDPI_IMAGES = YES; EXECUTABLE_PREFIX = ""; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ""; @@ -1129,7 +1129,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COMBINE_HIDPI_IMAGES = YES; EXECUTABLE_PREFIX = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; diff --git a/cocos/ui/UIScale9Sprite.cpp b/cocos/ui/UIScale9Sprite.cpp index 13f6f2f92d..f5e61c659e 100644 --- a/cocos/ui/UIScale9Sprite.cpp +++ b/cocos/ui/UIScale9Sprite.cpp @@ -814,8 +814,9 @@ y+=ytranslate; \ for(auto it=_children.cbegin()+i; it != _children.cend(); ++it) (*it)->visit(renderer, _modelViewTransform, flags); - // reset for next frame - _orderOfArrival = 0; + // FIX ME: Why need to set _orderOfArrival to 0?? + // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920 + // setOrderOfArrival(0); director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); diff --git a/extensions/GUI/CCScrollView/CCScrollView.cpp b/extensions/GUI/CCScrollView/CCScrollView.cpp index e97d2672be..68181bd899 100644 --- a/extensions/GUI/CCScrollView/CCScrollView.cpp +++ b/extensions/GUI/CCScrollView/CCScrollView.cpp @@ -343,6 +343,19 @@ void ScrollView::setContainer(Node * pContainer) this->setViewSize(this->_viewSize); } +bool ScrollView::hasVisibleParents() const +{ + auto parent = this->getParent(); + for( auto c = parent; c != nullptr; c = c->getParent() ) + { + if( !c->isVisible() ) + { + return false; + } + } + return true; +} + void ScrollView::relocateContainer(bool animated) { Vec2 oldPoint, min, max; @@ -625,7 +638,7 @@ void ScrollView::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t bool ScrollView::onTouchBegan(Touch* touch, Event* event) { - if (!this->isVisible()) + if (!this->isVisible() || !this->hasVisibleParents()) { return false; } diff --git a/extensions/GUI/CCScrollView/CCScrollView.h b/extensions/GUI/CCScrollView/CCScrollView.h index 72695df5c7..36f94d39f8 100644 --- a/extensions/GUI/CCScrollView/CCScrollView.h +++ b/extensions/GUI/CCScrollView/CCScrollView.h @@ -256,6 +256,8 @@ public: * CCActionTweenDelegate */ void updateTweenAction(float value, const std::string& key); + + bool hasVisibleParents() const; protected: /** * Relocates the container at the proper offset, in bounds of max/min offsets. diff --git a/templates/cocos2dx_files.json b/templates/cocos2dx_files.json index d7ce573238..be5c4b84d4 100644 --- a/templates/cocos2dx_files.json +++ b/templates/cocos2dx_files.json @@ -203,6 +203,8 @@ "cocos/3d/CCAnimationCurve.inl", "cocos/3d/CCAttachNode.cpp", "cocos/3d/CCAttachNode.h", + "cocos/3d/CCBillBoard.cpp", + "cocos/3d/CCBillBoard.h", "cocos/3d/CCBundle3D.cpp", "cocos/3d/CCBundle3D.h", "cocos/3d/CCBundle3DData.h", @@ -229,14 +231,24 @@ "cocos/3d/cocos3d.h", "cocos/Android.mk", "cocos/CMakeLists.txt", + "cocos/audio/AudioEngine.cpp", "cocos/audio/android/Android.mk", + "cocos/audio/android/AudioEngine-inl.cpp", + "cocos/audio/android/AudioEngine-inl.h", "cocos/audio/android/ccdandroidUtils.cpp", "cocos/audio/android/ccdandroidUtils.h", "cocos/audio/android/cddSimpleAudioEngine.cpp", "cocos/audio/android/jni/cddandroidAndroidJavaEngine.cpp", "cocos/audio/android/jni/cddandroidAndroidJavaEngine.h", + "cocos/audio/include/AudioEngine.h", "cocos/audio/include/Export.h", "cocos/audio/include/SimpleAudioEngine.h", + "cocos/audio/ios/AudioCache.h", + "cocos/audio/ios/AudioCache.mm", + "cocos/audio/ios/AudioEngine-inl.h", + "cocos/audio/ios/AudioEngine-inl.mm", + "cocos/audio/ios/AudioPlayer.h", + "cocos/audio/ios/AudioPlayer.mm", "cocos/audio/ios/CDAudioManager.h", "cocos/audio/ios/CDAudioManager.m", "cocos/audio/ios/CDConfig.h", @@ -662,6 +674,7 @@ "cocos/math/MathUtil.h", "cocos/math/MathUtil.inl", "cocos/math/MathUtilNeon.inl", + "cocos/math/MathUtilSSE.inl", "cocos/math/Quaternion.cpp", "cocos/math/Quaternion.h", "cocos/math/Quaternion.inl", diff --git a/tests/cpp-tests/Android.mk b/tests/cpp-tests/Android.mk index dba250329b..52eb45fcf3 100644 --- a/tests/cpp-tests/Android.mk +++ b/tests/cpp-tests/Android.mk @@ -16,6 +16,7 @@ Classes/ActionManagerTest/ActionManagerTest.cpp \ Classes/ActionsEaseTest/ActionsEaseTest.cpp \ Classes/ActionsProgressTest/ActionsProgressTest.cpp \ Classes/ActionsTest/ActionsTest.cpp \ +Classes/BillBoardTest/BillBoardTest.cpp \ Classes/Box2DTest/Box2dTest.cpp \ Classes/Box2DTestBed/Box2dView.cpp \ Classes/Box2DTestBed/GLES-Render.cpp \ @@ -38,6 +39,7 @@ Classes/ChipmunkTest/ChipmunkTest.cpp \ Classes/ClickAndMoveTest/ClickAndMoveTest.cpp \ Classes/ClippingNodeTest/ClippingNodeTest.cpp \ Classes/CocosDenshionTest/CocosDenshionTest.cpp \ +Classes/NewAudioEngineTest/NewAudioEngineTest.cpp \ Classes/ConfigurationTest/ConfigurationTest.cpp \ Classes/ConsoleTest/ConsoleTest.cpp \ Classes/CurlTest/CurlTest.cpp \ diff --git a/tests/cpp-tests/CMakeLists.txt b/tests/cpp-tests/CMakeLists.txt index c536fa9ed1..f3afd9c824 100644 --- a/tests/cpp-tests/CMakeLists.txt +++ b/tests/cpp-tests/CMakeLists.txt @@ -21,6 +21,7 @@ set(TESTS_SRC Classes/ActionsEaseTest/ActionsEaseTest.cpp Classes/ActionsProgressTest/ActionsProgressTest.cpp Classes/ActionsTest/ActionsTest.cpp + Classes/BillBoardTest/BillBoardTest.cpp Classes/Box2DTest/Box2dTest.cpp Classes/Box2DTestBed/Box2dView.cpp Classes/Box2DTestBed/GLES-Render.cpp diff --git a/tests/cpp-tests/Classes/BillBoardTest/BillBoardTest.cpp b/tests/cpp-tests/Classes/BillBoardTest/BillBoardTest.cpp new file mode 100644 index 0000000000..e06a4be1df --- /dev/null +++ b/tests/cpp-tests/Classes/BillBoardTest/BillBoardTest.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** + Copyright (c) 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 "BillBoardTest.h" +#include "3d/CCBillBoard.h" +#include "base/CCCamera.h" + +#include +#include "../testResource.h" + +enum +{ + IDC_NEXT = 100, + IDC_BACK, + IDC_RESTART +}; + +static int sceneIdx = -1; + + +static std::function createFunctions[] = +{ + CL(BillBoardTest) +}; + +#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) + +static Layer* nextSpriteTestAction() +{ + sceneIdx++; + sceneIdx = sceneIdx % MAX_LAYER; + + auto layer = (createFunctions[sceneIdx])(); + return layer; +} + +static Layer* backSpriteTestAction() +{ + sceneIdx--; + int total = MAX_LAYER; + if( sceneIdx < 0 ) + sceneIdx += total; + + auto layer = (createFunctions[sceneIdx])(); + return layer; +} + +static Layer* restartSpriteTestAction() +{ + auto layer = (createFunctions[sceneIdx])(); + return layer; +} + +BillBoardTest::BillBoardTest() +: _camera(nullptr) +{ + auto listener = EventListenerTouchAllAtOnce::create(); + listener->onTouchesMoved = CC_CALLBACK_2(BillBoardTest::onTouchesMoved, this); + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); + auto layer3D=Layer::create(); + addChild(layer3D,0); + _layerBillBorad=layer3D; + auto s = Director::getInstance()->getWinSize(); + if (_camera == nullptr) + { + _camera=Camera::createPerspective(60, (GLfloat)s.width/s.height, 1, 500); + _camera->setCameraFlag(CameraFlag::USER1); + _layerBillBorad->addChild(_camera); + } + + std::string imgs[3] = {"Images/Icon.png", "Images/r2.png"}; + for (unsigned int i = 0; i < 4; ++i) + { + Layer *layer = Layer::create(); + auto billboard = BillBoard::create(imgs[(unsigned int)(CCRANDOM_0_1() * 1 + 0.5)]); + billboard->setScale(0.5f); + billboard->setPosition3D(Vec3(0.0f, 0.0f, CCRANDOM_MINUS1_1() * 150.0f)); + billboard->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED); + billboard->setOpacity(CCRANDOM_0_1() * 128 + 128); + _billboards.push_back(billboard); + layer->addChild(billboard); + _layerBillBorad->addChild(layer); + layer->runAction( RepeatForever::create( RotateBy::create( CCRANDOM_0_1(), Vec3(0.0f, 45.0f, 0.0f) ) ) ); + } + + addNewBillBoradWithCoords(Vec3(20,5,0)); + addNewBillBoradWithCoords(Vec3(60,5,0)); + addNewBillBoradWithCoords(Vec3(100,5,0)); + addNewBillBoradWithCoords(Vec3(140,5,0)); + addNewBillBoradWithCoords(Vec3(180,5,0)); + addNewAniBillBoradWithCoords(Vec3(-20,0,0)); + addNewAniBillBoradWithCoords(Vec3(-60,0,0)); + addNewAniBillBoradWithCoords(Vec3(-100,0,0)); + addNewAniBillBoradWithCoords(Vec3(-140,0,0)); + addNewAniBillBoradWithCoords(Vec3(-180,0,0)); + _camera->setPosition3D(Vec3(0, 130, 230)); + _camera->lookAt(Vec3(0,0,100), Vec3(0,1,0)); + + TTFConfig ttfConfig("fonts/arial.ttf", 16); + auto label1 = Label::createWithTTF(ttfConfig,"rotate+"); + auto menuItem1 = MenuItemLabel::create(label1, CC_CALLBACK_1(BillBoardTest::rotateCameraCallback,this,10)); + auto label2 = Label::createWithTTF(ttfConfig,"rotate-"); + auto menuItem2 = MenuItemLabel::create(label2, CC_CALLBACK_1(BillBoardTest::rotateCameraCallback,this,-10)); + auto menu = Menu::create(menuItem1,menuItem2,NULL); + menu->setPosition(Vec2::ZERO); + menuItem1->setPosition( Vec2( s.width-80, VisibleRect::top().y-160) ); + menuItem2->setPosition( Vec2( s.width-80, VisibleRect::top().y-190) ); + addChild(menu, 0); + _layerBillBorad->setCameraMask(2); + + label1 = Label::createWithTTF(ttfConfig,"Point Oriented"); + menuItem1 = MenuItemLabel::create(label1,CC_CALLBACK_1(BillBoardTest::menuCallback_orientedPoint,this) ); + label2 = Label::createWithTTF(ttfConfig,"Plane Oriented"); + menuItem2 = MenuItemLabel::create(label2,CC_CALLBACK_1(BillBoardTest::menuCallback_orientedPlane,this) ); + menuItem1->setPosition( Vec2( s.width-80, VisibleRect::top().y-100) ); + menuItem2->setPosition( Vec2( s.width-80, VisibleRect::top().y-130) ); + + menu = Menu::create(menuItem1,menuItem2,NULL); + menu->setPosition(Vec2(0,0)); + this->addChild(menu, 10); + menuCallback_orientedPoint(nullptr); +} + +void BillBoardTest::menuCallback_orientedPoint(Ref* sender) +{ + for (auto& billboard : _billboards) { + billboard->setMode(BillBoard::Mode::VIEW_POINT_ORIENTED); + } +} + +void BillBoardTest::menuCallback_orientedPlane(Ref* sender) +{ + for (auto& billboard : _billboards) { + billboard->setMode(BillBoard::Mode::VIEW_PLANE_ORIENTED); + } +} + +BillBoardTest::~BillBoardTest() +{ + if (_camera) + { + _camera = nullptr; + } +} +std::string BillBoardTest::title() const +{ + return "Testing BillBoard"; +} +std::string BillBoardTest::subtitle() const +{ + return ""; +} +void BillBoardTest::addNewBillBoradWithCoords(Vec3 p) +{ + std::string imgs[3] = {"Images/Icon.png", "Images/r2.png"}; + for (unsigned int i = 0; i < 10; ++i) + { + auto billborad = BillBoard::create(imgs[(unsigned int)(CCRANDOM_0_1() * 1 + 0.5)]); + billborad->setScale(0.5f); + billborad->setPosition3D(Vec3(p.x, p.y, -150.0f + 30 * i)); + billborad->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED); + billborad->setOpacity(CCRANDOM_0_1() * 128 + 128); + _layerBillBorad->addChild(billborad); + _billboards.push_back(billborad); + } +} +void BillBoardTest::addNewAniBillBoradWithCoords(Vec3 p) +{ + for (unsigned int i = 0; i < 10; ++i) + { + auto billboradAni = BillBoard::create("Images/grossini.png"); + billboradAni->setScale(0.5f); + billboradAni->setPosition3D(Vec3(p.x, p.y, -150.0f + 30 * i)); + _layerBillBorad->addChild(billboradAni); + + auto animation = Animation::create(); + for( int i=1;i<15;i++) + { + char szName1[100] = {0}; + sprintf(szName1, "Images/grossini_dance_%02d.png", i); + animation->addSpriteFrameWithFile(szName1); + } + // should last 2.8 seconds. And there are 14 frames. + animation->setDelayPerUnit(2.8f / 14.0f); + animation->setRestoreOriginalFrame(true); + + auto action = Animate::create(animation); + billboradAni->runAction(RepeatForever::create(action)); + billboradAni->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED); + billboradAni->setOpacity(CCRANDOM_0_1() * 128 + 128); + _billboards.push_back(billboradAni); + } +} +void BillBoardTest::update(float dt) +{ + +} +void BillBoardTest::onTouchesMoved(const std::vector& touches, Event* event) +{ + if(touches.size()==1) + { + auto touch = touches[0]; + auto location = touch->getLocation(); + auto PreviousLocation = touch->getPreviousLocation(); + Point newPos = PreviousLocation - location; + + Vec3 cameraDir; + Vec3 cameraRightDir; + _camera->getNodeToWorldTransform().getForwardVector(&cameraDir); + cameraDir.normalize(); + cameraDir.y=0; + _camera->getNodeToWorldTransform().getRightVector(&cameraRightDir); + cameraRightDir.normalize(); + cameraRightDir.y=0; + Vec3 cameraPos= _camera->getPosition3D(); + cameraPos+=cameraDir*newPos.y*0.5; + cameraPos+=cameraRightDir*newPos.x*0.5; + _camera->setPosition3D(cameraPos); + } +} +void BillBoardTest::rotateCameraCallback(Ref* sender,float value) +{ + Vec3 rotation3D= _camera->getRotation3D(); + rotation3D.y+= value; + _camera->setRotation3D(rotation3D); +} + +void BillBoardTestScene::runThisTest() +{ + auto layer = nextSpriteTestAction(); + addChild(layer); + Director::getInstance()->replaceScene(this); +} diff --git a/tests/cpp-tests/Classes/BillBoardTest/BillBoardTest.h b/tests/cpp-tests/Classes/BillBoardTest/BillBoardTest.h new file mode 100644 index 0000000000..a2203b850d --- /dev/null +++ b/tests/cpp-tests/Classes/BillBoardTest/BillBoardTest.h @@ -0,0 +1,69 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#ifndef _BILLBOARD_TEST_H_ +#define _BILLBOARD_TEST_H_ + +#include "../testBasic.h" +#include "../BaseTest.h" +#include + +namespace cocos2d { + class BillBoard; + class Camera; +} + + + +class BillBoardTest : public BaseTest +{ +public: + virtual ~BillBoardTest(void); + CREATE_FUNC(BillBoardTest); + BillBoardTest(); + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual void update(float dt) override; + void addNewBillBoradWithCoords(Vec3 p); + void addNewAniBillBoradWithCoords(Vec3 p); + void rotateCameraCallback(Ref* sender,float value); + void onTouchesMoved(const std::vector& touches, Event* event); + + void menuCallback_orientedPoint(Ref* sender); + void menuCallback_orientedPlane(Ref* sender); + +protected: + Camera* _camera; + Layer* _layerBillBorad; + + std::vector _billboards; +}; + +class BillBoardTestScene : public TestScene +{ +public: + virtual void runThisTest(); +}; + +#endif diff --git a/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.cpp b/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.cpp new file mode 100644 index 0000000000..ae82703326 --- /dev/null +++ b/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.cpp @@ -0,0 +1,715 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS +#include "NewAudioEngineTest.h" +#include "ui/CocosGUI.h" + +using namespace cocos2d::ui; + +namespace { + +std::function createFunctions[] = +{ + CL(AudioControlTest), + CL(PlaySimultaneouslyTest), + CL(AudioProfileTest), + CL(InvalidAudioFileTest), + CL(LargeAudioFileTest) +}; + +unsigned int TEST_CASE_COUNT = sizeof(createFunctions) / sizeof(createFunctions[0]); + +int s_sceneIdx = -1; +Layer* createTest(int index) +{ + auto layer = (createFunctions[index])();; + return layer; +} + +Layer* nextAction() +{ + s_sceneIdx++; + s_sceneIdx = s_sceneIdx % TEST_CASE_COUNT; + + return createTest(s_sceneIdx); +} + +Layer* backAction() +{ + s_sceneIdx--; + if( s_sceneIdx < 0 ) + s_sceneIdx = TEST_CASE_COUNT -1; + + return createTest(s_sceneIdx); +} + +Layer* restartAction() +{ + return createTest(s_sceneIdx); +} + + class TextButton : public cocos2d::Label + { + public: + + static TextButton *create(const std::string& text, const std::function &onTriggered) + { + auto ret = new (std::nothrow) TextButton(); + + TTFConfig ttfconfig("fonts/arial.ttf",25); + if (ret && ret->setTTFConfig(ttfconfig)) { + ret->setString(text); + ret->_onTriggered = onTriggered; + + ret->autorelease(); + + return ret; + } + + delete ret; + return nullptr; + } + + void setEnabled(bool enabled) + { + _enabled = enabled; + if(_enabled){ + this->setColor(Color3B::WHITE); + } + else { + this->setColor(Color3B::GRAY); + } + } + + private: + TextButton() + : _enabled(true) + , _onTriggered(nullptr) + { + auto listener = EventListenerTouchOneByOne::create(); + listener->setSwallowTouches(true); + + listener->onTouchBegan = CC_CALLBACK_2(TextButton::onTouchBegan, this); + listener->onTouchEnded = CC_CALLBACK_2(TextButton::onTouchEnded, this); + listener->onTouchCancelled = CC_CALLBACK_2(TextButton::onTouchCancelled, this); + + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); + + } + + bool touchHits(Touch *touch) + { + auto hitPos = this->convertToNodeSpace(touch->getLocation()); + if (hitPos.x >= 0 && hitPos.y >= 0 && hitPos.x <= _contentSize.width && hitPos.y <= _contentSize.height) { + return true; + } + return false; + } + + bool onTouchBegan(Touch *touch, Event *event) + { + auto hits = touchHits(touch); + if (hits){ + scaleButtonTo(0.95f); + } + return hits; + } + + void onTouchEnded(Touch *touch, Event *event) + { + if(_enabled) { + auto hits = touchHits(touch); + if (hits && _onTriggered){ + _onTriggered(this); + } + } + + scaleButtonTo(1); + } + + void onTouchCancelled(Touch *touch, Event *event) + { + scaleButtonTo(1); + } + + void scaleButtonTo(float scale) + { + auto action = ScaleTo::create(0.05f, scale); + action->setTag(10000); + stopActionByTag(10000); + runAction(action); + } + + std::function _onTriggered; + + bool _enabled; + }; + + class SliderEx : public ui::Slider + { + public: + enum class TouchEvent + { + DOWN, + MOVE, + UP, + CANCEL + }; + typedef std::function ccSliderExCallback; + + static SliderEx* create(){ + auto ret = new (std::nothrow) SliderEx(); + if (ret && ret->init()) + { + ret->_callback = nullptr; + ret->loadBarTexture("cocosui/sliderTrack.png"); + ret->loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", ""); + ret->loadProgressBarTexture("cocosui/sliderProgress.png"); + + ret->autorelease(); + + return ret; + } + CC_SAFE_DELETE(ret); + return ret; + } + + void setCallBack(const ccSliderExCallback& callback){ + _callback = callback; + } + + void setRatio(float ratio) { + if (ratio > 1.0f){ + ratio = 1.0f; + } + else if (ratio < 0.0f){ + ratio = 0.0f; + } + + _ratio = ratio; + _percent = 100 * _ratio; + + float dis = _barLength * _ratio; + _slidBallRenderer->setPosition(Vec2(dis, _contentSize.height / 2.0f)); + if (_scale9Enabled){ + _progressBarRenderer->setPreferredSize(Size(dis,_progressBarTextureSize.height)); + } + else + { + auto spriteRenderer = _progressBarRenderer->getSprite(); + + if (nullptr != spriteRenderer) { + Rect rect = spriteRenderer->getTextureRect(); + rect.size.width = _progressBarTextureSize.width * _ratio; + spriteRenderer->setTextureRect(rect, spriteRenderer->isTextureRectRotated(), rect.size); + } + } + } + + virtual bool onTouchBegan(Touch *touch, Event *unusedEvent) override{ + auto ret = Slider::onTouchBegan(touch, unusedEvent); + if(ret && _callback){ + _touchEvent = TouchEvent::DOWN; + Vec2 nsp = convertToNodeSpace(_touchBeganPosition); + _ratio = nsp.x / _barLength; + if(_ratio < 0.0f) + _ratio = 0.0f; + else if(_ratio > 1.0f) + _ratio = 1.0f; + _callback(this,_ratio,_touchEvent); + } + return ret; + } + + virtual void onTouchMoved(Touch *touch, Event *unusedEvent) override{ + _touchEvent = TouchEvent::MOVE; + Slider::onTouchMoved(touch, unusedEvent); + Vec2 nsp = convertToNodeSpace(_touchMovePosition); + _ratio = nsp.x / _barLength; + if(_ratio < 0.0f) + _ratio = 0.0f; + else if(_ratio > 1.0f) + _ratio = 1.0f; + if(_callback){ + _callback(this,_ratio,_touchEvent); + } + } + + virtual void onTouchEnded(Touch *touch, Event *unusedEvent) override{ + _touchEvent = TouchEvent::UP; + Slider::onTouchEnded(touch, unusedEvent); + Vec2 nsp = convertToNodeSpace(_touchEndPosition); + _ratio = nsp.x / _barLength; + if(_ratio < 0.0f) + _ratio = 0.0f; + else if(_ratio > 1.0f) + _ratio = 1.0f; + if(_callback){ + _callback(this,_ratio,_touchEvent); + } + } + + virtual void onTouchCancelled(Touch *touch, Event *unusedEvent) override{ + _touchEvent = TouchEvent::CANCEL; + Slider::onTouchCancelled(touch, unusedEvent); + + if(_callback){ + _callback(this,_ratio,_touchEvent); + } + } + + private: + TouchEvent _touchEvent; + float _ratio; + ccSliderExCallback _callback; + }; +} + +void AudioEngineTestScene::runThisTest() +{ + CCASSERT(AudioEngine::lazyInit(),"Fail to initialize AudioEngine!"); + + s_sceneIdx = -1; + auto layer = nextAction(); + addChild(layer); + + Director::getInstance()->replaceScene(this); +} + +void AudioEngineTestDemo::backCallback(Ref* sender) +{ + AudioEngine::stopAll(); + auto scene = new AudioEngineTestScene(); + auto layer = backAction(); + + scene->addChild(layer); + Director::getInstance()->replaceScene(scene); + scene->release(); +} + +void AudioEngineTestDemo::nextCallback(Ref* sender) +{ + AudioEngine::stopAll(); + auto scene = new AudioEngineTestScene(); + auto layer = nextAction(); + + scene->addChild(layer); + Director::getInstance()->replaceScene(scene); + scene->release(); +} + +void AudioEngineTestDemo::restartCallback(Ref* sender) +{ + AudioEngine::stopAll(); + auto scene = new AudioEngineTestScene(); + auto layer = restartAction(); + + scene->addChild(layer); + Director::getInstance()->replaceScene(scene); + scene->release(); +} + +std::string AudioEngineTestDemo::title() const +{ + return "New Audio Engine Test"; +} + +// AudioControlTest +bool AudioControlTest::init() +{ + auto ret = AudioEngineTestDemo::init(); + _audioID = AudioEngine::INVAILD_AUDIO_ID; + _loopEnabled = false; + _volume = 1.0f; + _duration = AudioEngine::TIME_UNKNOWN; + _timeRatio = 0.0f; + _updateTimeSlider = true; + + std::string fontFilePath = "fonts/arial.ttf"; + + auto& layerSize = this->getContentSize(); + + auto playItem = TextButton::create("play", [&](TextButton* button){ + if (_audioID == AudioEngine::INVAILD_AUDIO_ID) { + _audioID = AudioEngine::play2d("background.mp3", _loopEnabled, _volume); + + if(_audioID != AudioEngine::INVAILD_AUDIO_ID) { + button->setEnabled(false); + AudioEngine::setFinishCallback(_audioID, [&](int id, const std::string& filePath){ + _audioID = AudioEngine::INVAILD_AUDIO_ID; + ((TextButton*)_playItem)->setEnabled(true); + + _timeRatio = 0.0f; + ((SliderEx*)_timeSlider)->setRatio(_timeRatio); + }); + } + } + }); + _playItem = playItem; + playItem->setPosition(layerSize.width * 0.3f,layerSize.height * 0.7f); + addChild(playItem); + + auto stopItem = TextButton::create("stop", [&](TextButton* button){ + if (_audioID != AudioEngine::INVAILD_AUDIO_ID ) { + AudioEngine::stop(_audioID); + + _audioID = AudioEngine::INVAILD_AUDIO_ID; + ((TextButton*)_playItem)->setEnabled(true); + } + }); + stopItem->setPosition(layerSize.width * 0.7f,layerSize.height * 0.7f); + addChild(stopItem); + + auto pauseItem = TextButton::create("pause", [&](TextButton* button){ + if (_audioID != AudioEngine::INVAILD_AUDIO_ID ) { + AudioEngine::pause(_audioID); + } + }); + pauseItem->setPosition(layerSize.width * 0.3f,layerSize.height * 0.6f); + addChild(pauseItem); + + auto resumeItem = TextButton::create("resume", [&](TextButton* button){ + if (_audioID != AudioEngine::INVAILD_AUDIO_ID ) { + AudioEngine::resume(_audioID); + } + }); + resumeItem->setPosition(layerSize.width * 0.7f,layerSize.height * 0.6f); + addChild(resumeItem); + + auto loopItem = TextButton::create("enable-loop", [&](TextButton* button){ + _loopEnabled = !_loopEnabled; + + if (_audioID != AudioEngine::INVAILD_AUDIO_ID ) { + AudioEngine::setLoop(_audioID, _loopEnabled); + } + if(_loopEnabled){ + button->setString("disable-loop"); + } + else { + button->setString("enable-loop"); + } + }); + loopItem->setPosition(layerSize.width * 0.3f,layerSize.height * 0.5f); + addChild(loopItem); + + auto uncacheItem = TextButton::create("uncache", [&](TextButton* button){ + AudioEngine::uncache("background.mp3"); + + _audioID = AudioEngine::INVAILD_AUDIO_ID; + ((TextButton*)_playItem)->setEnabled(true); + }); + uncacheItem->setPosition(layerSize.width * 0.7f,layerSize.height * 0.5f); + addChild(uncacheItem); + + auto volumeSlider = SliderEx::create(); + volumeSlider->setPercent(100); + volumeSlider->setCallBack([&](SliderEx* sender,float ratio,SliderEx::TouchEvent event){ + _volume = ratio; + log("_volume:%f,event:%d",_volume,event); + if (_audioID != AudioEngine::INVAILD_AUDIO_ID ) { + AudioEngine::setVolume(_audioID, _volume); + } + }); + volumeSlider->setPosition(Vec2(layerSize.width * 0.5f,layerSize.height * 0.35f)); + addChild(volumeSlider); + + auto timeSlider = SliderEx::create(); + timeSlider->setCallBack([&](SliderEx* sender,float ratio,SliderEx::TouchEvent event){ + switch(event){ + case SliderEx::TouchEvent::MOVE: + case SliderEx::TouchEvent::DOWN: + _updateTimeSlider = false; + break; + case SliderEx::TouchEvent::UP: + if (_audioID != AudioEngine::INVAILD_AUDIO_ID && _duration != AudioEngine::TIME_UNKNOWN) { + AudioEngine::setCurrentTime(_audioID,_duration * ratio); + } + case SliderEx::TouchEvent::CANCEL: + _updateTimeSlider = true; + break; + } + }); + timeSlider->setPosition(Vec2(layerSize.width * 0.5f,layerSize.height * 0.25f)); + addChild(timeSlider); + _timeSlider = timeSlider; + + auto& volumeSliderPos = volumeSlider->getPosition(); + auto& sliderSize = volumeSlider->getContentSize(); + auto volumeLabel = Label::createWithTTF("volume: ", fontFilePath, 20); + volumeLabel->setAnchorPoint(Vec2::ANCHOR_MIDDLE_RIGHT); + volumeLabel->setPosition(volumeSliderPos.x - sliderSize.width / 2, volumeSliderPos.y); + addChild(volumeLabel); + + auto& timeSliderPos = timeSlider->getPosition(); + auto timeLabel = Label::createWithTTF("time: ", fontFilePath, 20); + timeLabel->setAnchorPoint(Vec2::ANCHOR_MIDDLE_RIGHT); + timeLabel->setPosition(timeSliderPos.x - sliderSize.width / 2, timeSliderPos.y); + addChild(timeLabel); + + this->schedule(schedule_selector(AudioControlTest::update), 0.1f); + + return ret; +} + +void AudioControlTest::update(float dt) +{ + if (_audioID != AudioEngine::INVAILD_AUDIO_ID ) { + if(_duration == AudioEngine::TIME_UNKNOWN){ + _duration = AudioEngine::getDuration(_audioID); + } + if(_duration != AudioEngine::TIME_UNKNOWN){ + auto time = AudioEngine::getCurrentTime(_audioID); + _timeRatio = time / _duration; + if(_updateTimeSlider){ + ((SliderEx*)_timeSlider)->setRatio(_timeRatio); + } + } + } +} + +AudioControlTest::~AudioControlTest() +{ +} + +std::string AudioControlTest::title() const +{ + return "audio control test"; +} + +// PlaySimultaneouslyTest +bool PlaySimultaneouslyTest::init() +{ + auto ret = AudioEngineTestDemo::init(); + + char text[36]; + int tmp = 81; + for(int index = 0; index < TEST_COUNT; ++index){ + sprintf(text,"audio/SoundEffectsFX009/FX0%d.mp3",tmp + index); + _files[index] = text; + } + _playingcount = 0; + + auto playItem = TextButton::create("play-simultaneously", [&](TextButton* button){ + int audioId; + _playingcount = 0; + button->setEnabled(false); + auto startTime = utils::gettime(); + for(int index = 0; index < TEST_COUNT; ++index){ + audioId = AudioEngine::play2d(_files[index]); + if(audioId != AudioEngine::INVAILD_AUDIO_ID){ + _playingcount += 1; + + AudioEngine::setFinishCallback(audioId, [&](int id, const std::string& filePath){ + _playingcount -= 1; + if(_playingcount <= 0){ + ((TextButton*)_playItem)->setEnabled(true); + } + }); + } + else { + log("%s,%d,Fail to play file:%s",__FILE__,__LINE__ ,_files[index].c_str()); + } + } + log("diff time:%lf",utils::gettime() - startTime); + }); + playItem->setNormalizedPosition(Vec2(0.5f,0.5f)); + this->addChild(playItem); + _playItem = playItem; + + return ret; +} + +PlaySimultaneouslyTest::~PlaySimultaneouslyTest() +{ +} + +std::string PlaySimultaneouslyTest::title() const +{ + return "Simultaneously play multiple audio"; +} + +// AudioProfileTest +bool AudioProfileTest::init() +{ + auto ret = AudioEngineTestDemo::init(); + + char text[30]; + _files[0] = "background.mp3"; +#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS + _files[1] = "background.caf"; +#else + _files[1] = "background.ogg"; +#endif + _files[2] = "background.wav"; + _files[3] = "pew-pew-lei.wav"; + + std::string fontFilePath = "fonts/arial.ttf"; + _minDelay = 1.0f; + _time = 0.0f; + + _audioProfile.name = "AudioProfileTest"; + _audioProfile.maxInstances = 3; + _audioProfile.minDelay = 1.0; + + Vec2 pos(0.5f,0.7f); + + for(int index = 0; index < FILE_COUNT; ++index){ + sprintf(text,"play %s",_files[index].c_str()); + + auto playItem = TextButton::create(text, [&](TextButton* button){ + int index = button->getTag(); + auto id = AudioEngine::play2d(_files[index], false, 1.0f, &_audioProfile); + if(id != AudioEngine::INVAILD_AUDIO_ID){ + _time = _minDelay; + _audioCount += 1; + char show[30]; + sprintf(show,"audio count:%d",_audioCount); + _showLabel->setString(show); + + AudioEngine::setFinishCallback(id, [&](int id, const std::string& filePath){ + _audioCount -= 1; + char show[30]; + sprintf(show,"audio count:%d",_audioCount); + _showLabel->setString(show); + }); + } + + }); + playItem->setTag(index); + playItem->setNormalizedPosition(pos); + this->addChild(playItem); + pos.y -= 0.1f; + + } + + Vec2 origin = Director::getInstance()->getVisibleOrigin(); + Size size = Director::getInstance()->getVisibleSize(); + + auto profileInfoLabel = Label::createWithTTF("AudioProfile Info:\n max instance:3 \n minimum delay:1.0", fontFilePath, 12); + profileInfoLabel->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT); + profileInfoLabel->setPosition(Vec2(origin.x, origin.y + size.height * 0.65f)); + addChild(profileInfoLabel); + + _audioCount = 0; + _showLabel = Label::createWithTTF("audio count:0", fontFilePath, 12); + _showLabel->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT); + _showLabel->setPosition(Vec2(origin.x, origin.y + size.height * 0.5f)); + addChild(_showLabel); + + auto timeSlider = SliderEx::create(); + timeSlider->setEnabled(false); + timeSlider->setNormalizedPosition(pos); + addChild(timeSlider); + _timeSlider = timeSlider; + + this->schedule(schedule_selector(AudioControlTest::update), 0.05f); + + return ret; +} + +void AudioProfileTest::update(float dt) +{ + if(_time > 0.0f) + { + _time -= dt; + ((SliderEx*)_timeSlider)->setRatio(_time / _minDelay); + } +} + +AudioProfileTest::~AudioProfileTest() +{ +} + +std::string AudioProfileTest::title() const +{ + return "AudioProfileTest"; +} + +std::string AudioProfileTest::subtitle() const +{ + return "See the console."; +} + +// InvalidAudioFileTest +bool InvalidAudioFileTest::init() +{ + auto ret = AudioEngineTestDemo::init(); + + auto playItem = TextButton::create("play unsupported media type", [&](TextButton* button){ +#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS + AudioEngine::play2d("background.ogg"); +#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID + AudioEngine::play2d("background.caf"); +#endif + }); + playItem->setNormalizedPosition(Vec2(0.5f, 0.6f)); + this->addChild(playItem); + + auto playItem2 = TextButton::create("play not-existent file", [&](TextButton* button){ + AudioEngine::play2d("not-existent file.mp3"); + }); + playItem2->setNormalizedPosition(Vec2(0.5f, 0.4f)); + this->addChild(playItem2); + + return ret; +} + +InvalidAudioFileTest::~InvalidAudioFileTest() +{ +} + +std::string InvalidAudioFileTest::title() const +{ + return "Test invalid audio file"; +} + +std::string InvalidAudioFileTest::subtitle() const +{ + return "Not crash,please see the console."; +} + +// LargeAudioFileTest +bool LargeAudioFileTest::init() +{ + auto ret = AudioEngineTestDemo::init(); + + auto playItem = TextButton::create("play large audio file", [&](TextButton* button){ + AudioEngine::play2d("audio/Chee Lai(Arise).mp3"); + }); + playItem->setNormalizedPosition(Vec2::ANCHOR_MIDDLE); + this->addChild(playItem); + + return ret; +} + +LargeAudioFileTest::~LargeAudioFileTest() +{ +} + +std::string LargeAudioFileTest::title() const +{ + return "Test large audio file"; +} + +#endif diff --git a/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.h b/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.h new file mode 100644 index 0000000000..e4c2133b6a --- /dev/null +++ b/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.h @@ -0,0 +1,153 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS +#ifndef __NEWAUDIOENGINE_TEST_H_ +#define __NEWAUDIOENGINE_TEST_H_ + +#include "cocos2d.h" +#include "../testBasic.h" +#include "../BaseTest.h" + +#include "audio/include/AudioEngine.h" + +using namespace cocos2d; + +class AudioEngineTestScene : public TestScene +{ +public: + virtual void runThisTest(); +}; + +class AudioEngineTestDemo : public BaseTest +{ +public: + virtual std::string title() const override; + void backCallback(Ref* sender); + void nextCallback(Ref* sender); + void restartCallback(Ref* sender); + +}; + +class AudioControlTest : public AudioEngineTestDemo +{ +public: + CREATE_FUNC(AudioControlTest); + + virtual ~AudioControlTest(); + + virtual bool init(); + + virtual void update(float dt); + + virtual std::string title() const override; + +private: + int _audioID; + bool _loopEnabled; + float _volume; + float _duration; + float _timeRatio; + + void* _playItem; + void* _timeSlider; + bool _updateTimeSlider; +}; + +class PlaySimultaneouslyTest : public AudioEngineTestDemo +{ +public: + CREATE_FUNC(PlaySimultaneouslyTest); + + virtual ~PlaySimultaneouslyTest(); + + virtual bool init(); + + virtual std::string title() const override; +private: + static const int TEST_COUNT = 10; + std::string _files[TEST_COUNT]; + + void* _playItem; + int _playingcount; +}; + +class AudioProfileTest : public AudioEngineTestDemo +{ +public: + CREATE_FUNC(AudioProfileTest); + + virtual ~AudioProfileTest(); + + virtual bool init(); + + virtual std::string title() const override; + virtual std::string subtitle() const override; + + virtual void update(float dt); + +private: + static const int FILE_COUNT = 4; + std::string _files[FILE_COUNT]; + AudioProfile _audioProfile; + + int _audioCount; + Label* _showLabel; + float _time; + float _minDelay; + void* _timeSlider; +}; + +class InvalidAudioFileTest : public AudioEngineTestDemo +{ +public: + CREATE_FUNC(InvalidAudioFileTest); + + virtual ~InvalidAudioFileTest(); + + virtual bool init(); + + virtual std::string title() const override; + virtual std::string subtitle() const override; + +private: + +}; + +class LargeAudioFileTest : public AudioEngineTestDemo +{ +public: + CREATE_FUNC(LargeAudioFileTest); + + virtual ~LargeAudioFileTest(); + + virtual bool init(); + + virtual std::string title() const override; + +private: + +}; + +#endif /* defined(__NEWAUDIOENGINE_TEST_H_) */ +#endif diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index fdda2d5d75..f6ae432436 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -999,22 +999,22 @@ Sprite3DReskinTest::Sprite3DReskinTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DReskinTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - TTFConfig ttfConfig("fonts/arial.ttf", 20); + TTFConfig ttfConfig("fonts/arial.ttf", 20); auto label1 = Label::createWithTTF(ttfConfig,"Hair"); - auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchHair,this) ); + auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchHair,this) ); auto label2 = Label::createWithTTF(ttfConfig,"Glasses"); - auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchGlasses,this) ); + auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchGlasses,this) ); auto label3 = Label::createWithTTF(ttfConfig,"Coat"); - auto item3 = MenuItemLabel::create(label3,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchCoat,this) ); + auto item3 = MenuItemLabel::create(label3,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchCoat,this) ); auto label4 = Label::createWithTTF(ttfConfig,"Pants"); - auto item4 = MenuItemLabel::create(label4, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchPants,this) ); + auto item4 = MenuItemLabel::create(label4, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchPants,this) ); auto label5 = Label::createWithTTF(ttfConfig,"Shoes"); - auto item5 = MenuItemLabel::create(label5,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchShoes,this) ); + auto item5 = MenuItemLabel::create(label5,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_switchShoes,this) ); item1->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height*4 ) ); - item2->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height *5 ) ); - item3->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height*6 ) ); - item4->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height *7 ) ); - item5->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height *8 ) ); + item2->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height *5 ) ); + item3->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height*6 ) ); + item4->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height *7 ) ); + item5->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height *8 ) ); auto pMenu1 = CCMenu::create(item1,item2,item3,item4,item5,NULL); pMenu1->setPosition(Vec2(0,0)); this->addChild(pMenu1, 10); diff --git a/tests/cpp-tests/Classes/controller.cpp b/tests/cpp-tests/Classes/controller.cpp index e677a5cecc..b5864d45ac 100644 --- a/tests/cpp-tests/Classes/controller.cpp +++ b/tests/cpp-tests/Classes/controller.cpp @@ -39,6 +39,9 @@ Controller g_aTestNames[] = { { "Actions - Ease", [](){return new ActionsEaseTestScene();} }, { "Actions - Progress", [](){return new ProgressActionsTestScene(); } }, { "Audio - CocosDenshion", []() { return new CocosDenshionTestScene(); } }, +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + { "Audio - NewAudioEngine", []() { return new AudioEngineTestScene(); } }, +#endif { "Box2d - Basic", []() { return new Box2DTestScene(); } }, { "Box2d - TestBed", []() { return new Box2dTestBedScene(); } }, { "Bugs", []() { return new BugsTestScene(); } }, @@ -60,6 +63,7 @@ Controller g_aTestNames[] = { { "FileUtils", []() { return new FileUtilsTestScene(); } }, { "Fonts", []() { return new FontTestScene(); } }, { "Interval", [](){return new IntervalTestScene(); } }, + { "Node: BillBoard Test", [](){ return new BillBoardTestScene(); }}, { "Node: Camera 3D Test", [](){ return new Camera3DTestScene(); }}, { "Node: Clipping", []() { return new ClippingNodeTestScene(); } }, { "Node: Draw", [](){return new DrawPrimitivesTestScene();} }, diff --git a/tests/cpp-tests/Classes/tests.h b/tests/cpp-tests/Classes/tests.h index 5f0f139b23..0fd5748a1e 100644 --- a/tests/cpp-tests/Classes/tests.h +++ b/tests/cpp-tests/Classes/tests.h @@ -37,6 +37,9 @@ #include "PerformanceTest/PerformanceTest.h" #include "ZwoptexTest/ZwoptexTest.h" #include "CocosDenshionTest/CocosDenshionTest.h" +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS) +#include "NewAudioEngineTest/NewAudioEngineTest.h" +#endif #if (CC_TARGET_PLATFORM != CC_PLATFORM_EMSCRIPEN) #if (CC_TARGET_PLATFORM != CC_PLATFORM_MARMALADE) // bada don't support libcurl @@ -70,5 +73,6 @@ #include "Sprite3DTest/Sprite3DTest.h" #include "Camera3DTest/Camera3DTest.h" +#include "BillBoardTest/BillBoardTest.h" #endif diff --git a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj index f99a6c4cc7..7b0aed96a9 100644 --- a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj +++ b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj @@ -137,6 +137,7 @@ + @@ -316,6 +317,7 @@ + diff --git a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters index f0e771d566..d5b25f0b12 100644 --- a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters +++ b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters @@ -325,6 +325,9 @@ {7f85be1c-98c5-4412-afc5-6f39ae1452a7} + + {54a30b92-ddfb-420e-908b-886c23c21cf1} + @@ -858,6 +861,9 @@ Classes\UITest\CocostudioGUISceneTest + + Classes\BillBoardTest + @@ -1589,5 +1595,8 @@ Classes\UITest\CocostudioGUISceneTest + + Classes\BillBoardTest + \ No newline at end of file diff --git a/tools/bindings-generator b/tools/bindings-generator index c1db553615..a8496d540c 160000 --- a/tools/bindings-generator +++ b/tools/bindings-generator @@ -1 +1 @@ -Subproject commit c1db553615789a1545d495d0d0fd6f620547f99d +Subproject commit a8496d540c174236bec0d5a33457340571699f19 diff --git a/tools/tolua/cocos2dx.ini b/tools/tolua/cocos2dx.ini index d6894e123b..dec87dfd0a 100644 --- a/tools/tolua/cocos2dx.ini +++ b/tools/tolua/cocos2dx.ini @@ -11,7 +11,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android cocos_flags = -DANDROID @@ -136,7 +136,8 @@ skip = Node::[setGLServerState description getUserObject .*UserData getGLServerS Animation3DCache::[*], Sprite3DMaterialCache::[*], Sprite3DCache::[*], - Bone3D::[*] + Bone3D::[*], + BillBoard::[*] rename_functions = SpriteFrameCache::[addSpriteFramesWithFile=addSpriteFrames getSpriteFrameByName=getSpriteFrame], ProgressTimer::[setReverseProgress=setReverseDirection], diff --git a/tools/tolua/cocos2dx_3d.ini b/tools/tolua/cocos2dx_3d.ini index a043f994f9..f12bd68618 100644 --- a/tools/tolua/cocos2dx_3d.ini +++ b/tools/tolua/cocos2dx_3d.ini @@ -11,7 +11,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android cocos_flags = -DANDROID @@ -44,7 +44,8 @@ skip = Mesh::[create getAABB], Bone3D::[*], Ray::[*], AABB::[*], - OBB::[*] + OBB::[*], + BillBoard::[create] rename_functions = diff --git a/tools/tolua/cocos2dx_cocosbuilder.ini b/tools/tolua/cocos2dx_cocosbuilder.ini index 40a7de384b..410fdeb5a5 100644 --- a/tools/tolua/cocos2dx_cocosbuilder.ini +++ b/tools/tolua/cocos2dx_cocosbuilder.ini @@ -11,7 +11,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/platform/android diff --git a/tools/tolua/cocos2dx_cocosdenshion.ini b/tools/tolua/cocos2dx_cocosdenshion.ini index b032989626..6e337f3b84 100644 --- a/tools/tolua/cocos2dx_cocosdenshion.ini +++ b/tools/tolua/cocos2dx_cocosdenshion.ini @@ -11,7 +11,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android diff --git a/tools/tolua/cocos2dx_controller.ini b/tools/tolua/cocos2dx_controller.ini index d80733b677..aed359d313 100644 --- a/tools/tolua/cocos2dx_controller.ini +++ b/tools/tolua/cocos2dx_controller.ini @@ -13,7 +13,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/base -I%(cocosdir)s/cocos/platform/android cocos_flags = -DANDROID diff --git a/tools/tolua/cocos2dx_experimental.ini b/tools/tolua/cocos2dx_experimental.ini index 97d890abf1..3ab59b7e59 100644 --- a/tools/tolua/cocos2dx_experimental.ini +++ b/tools/tolua/cocos2dx_experimental.ini @@ -11,7 +11,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/platform/android diff --git a/tools/tolua/cocos2dx_experimental_video.ini b/tools/tolua/cocos2dx_experimental_video.ini index e0c343b56e..3f92bf13d7 100644 --- a/tools/tolua/cocos2dx_experimental_video.ini +++ b/tools/tolua/cocos2dx_experimental_video.ini @@ -13,7 +13,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/platform/android diff --git a/tools/tolua/cocos2dx_extension.ini b/tools/tolua/cocos2dx_extension.ini index 3b474c792f..162ebddd02 100644 --- a/tools/tolua/cocos2dx_extension.ini +++ b/tools/tolua/cocos2dx_extension.ini @@ -11,7 +11,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android diff --git a/tools/tolua/cocos2dx_physics.ini b/tools/tolua/cocos2dx_physics.ini index dca3e11f6f..c5042f1dde 100644 --- a/tools/tolua/cocos2dx_physics.ini +++ b/tools/tolua/cocos2dx_physics.ini @@ -13,7 +13,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android diff --git a/tools/tolua/cocos2dx_spine.ini b/tools/tolua/cocos2dx_spine.ini index 9ab910e8a2..b43c0ca4e3 100644 --- a/tools/tolua/cocos2dx_spine.ini +++ b/tools/tolua/cocos2dx_spine.ini @@ -11,7 +11,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/platform/android diff --git a/tools/tolua/cocos2dx_studio.ini b/tools/tolua/cocos2dx_studio.ini index a25e3b67b9..5aaf483758 100644 --- a/tools/tolua/cocos2dx_studio.ini +++ b/tools/tolua/cocos2dx_studio.ini @@ -14,7 +14,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s/external -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/platform/android diff --git a/tools/tolua/cocos2dx_ui.ini b/tools/tolua/cocos2dx_ui.ini index 1852a16b97..90258ae875 100644 --- a/tools/tolua/cocos2dx_ui.ini +++ b/tools/tolua/cocos2dx_ui.ini @@ -14,7 +14,7 @@ android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include -clang_flags = -nostdinc -x c++ -std=c++11 +clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/platform/android