diff --git a/frameworks/cocos2d-html5 b/frameworks/cocos2d-html5 index 9aed43ac69..fa68c45229 160000 --- a/frameworks/cocos2d-html5 +++ b/frameworks/cocos2d-html5 @@ -1 +1 @@ -Subproject commit 9aed43ac69ae1f3b5f0a1257b845d5481263391d +Subproject commit fa68c45229f8929fab5b73a7679896804880cb58 diff --git a/frameworks/js-bindings/bindings/manual/ScriptingCore.cpp b/frameworks/js-bindings/bindings/manual/ScriptingCore.cpp index a10a402f29..67c2ba1a6f 100644 --- a/frameworks/js-bindings/bindings/manual/ScriptingCore.cpp +++ b/frameworks/js-bindings/bindings/manual/ScriptingCore.cpp @@ -354,6 +354,24 @@ bool JSBCore_os(JSContext *cx, uint32_t argc, jsval *vp) return true; }; +bool JSB_cleanScript(JSContext *cx, uint32_t argc, jsval *vp) +{ + if (argc != 1) + { + JS_ReportError(cx, "Invalid number of arguments in JSB_cleanScript"); + return false; + } + jsval *argv = JS_ARGV(cx, vp); + JSString *jsPath = JSVAL_TO_STRING(argv[0]); + JSB_PRECONDITION2(jsPath, cx, false, "Error js file in clean script"); + JSStringWrapper wrapper(jsPath); + ScriptingCore::getInstance()->cleanScript(wrapper.get()); + + JS_SET_RVAL(cx, vp, JSVAL_VOID); + + return true; +}; + bool JSB_core_restartVM(JSContext *cx, uint32_t argc, jsval *vp) { JSB_PRECONDITION2(argc==0, cx, false, "Invalid number of arguments in executeScript"); @@ -394,11 +412,12 @@ void registerDefaultClasses(JSContext* cx, JSObject* global) { JS_DefineFunction(cx, global, "log", ScriptingCore::log, 0, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(cx, global, "executeScript", ScriptingCore::executeScript, 1, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(cx, global, "forceGC", ScriptingCore::forceGC, 0, JSPROP_READONLY | JSPROP_PERMANENT); - + JS_DefineFunction(cx, global, "__getPlatform", JSBCore_platform, 0, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(cx, global, "__getOS", JSBCore_os, 0, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(cx, global, "__getVersion", JSBCore_version, 0, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(cx, global, "__restartVM", JSB_core_restartVM, 0, JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_ENUMERATE ); + JS_DefineFunction(cx, global, "__cleanScript", JSB_cleanScript, 1, JSPROP_READONLY | JSPROP_PERMANENT); } static void sc_finalize(JSFreeOp *freeOp, JSObject *obj) { @@ -422,6 +441,11 @@ ScriptingCore::ScriptingCore() // set utf8 strings internally (we don't need utf16) // XXX: Removed in SpiderMonkey 19.0 //JS_SetCStringsAreUTF8(); + initRegister(); +} + +void ScriptingCore::initRegister() +{ this->addRegisterCallback(registerDefaultClasses); this->_runLoop = new SimpleRunLoop(); } @@ -703,9 +727,15 @@ bool ScriptingCore::runScript(const char *path, JSObject* global, JSContext* cx) } void ScriptingCore::reset() +{ + Director::getInstance()->restart(); +} + +void ScriptingCore::restartVM() { cleanup(); - start(); + initRegister(); + CCApplication::getInstance()->applicationDidFinishLaunching(); } ScriptingCore::~ScriptingCore() @@ -741,6 +771,7 @@ void ScriptingCore::cleanup() _js_global_type_map.clear(); filename_script.clear(); + registrationList.clear(); } void ScriptingCore::reportError(JSContext *cx, const char *message, JSErrorReport *report) @@ -1344,6 +1375,13 @@ int ScriptingCore::sendEvent(ScriptEvent* evt) if (NULL == evt) return 0; + // special type, can't use this code after JSAutoCompartment + if (evt->type == kRestartGame) + { + restartVM(); + return 0; + } + JSAutoCompartment ac(_cx, _global); switch (evt->type) diff --git a/frameworks/js-bindings/bindings/manual/ScriptingCore.h b/frameworks/js-bindings/bindings/manual/ScriptingCore.h index 0ae50e5a18..742a82c62a 100644 --- a/frameworks/js-bindings/bindings/manual/ScriptingCore.h +++ b/frameworks/js-bindings/bindings/manual/ScriptingCore.h @@ -247,7 +247,7 @@ class ScriptingCore : public cocos2d::ScriptEngineProtocol private: void string_report(jsval val); - + void initRegister(); public: int handleNodeEvent(void* data); int handleComponentEvent(void* data); @@ -257,6 +257,8 @@ class ScriptingCore : public cocos2d::ScriptEngineProtocol bool handleTouchEvent(void* nativeObj, cocos2d::EventTouch::EventCode eventCode, cocos2d::Touch* touch, cocos2d::Event* event, jsval* jsvalRet = nullptr); bool handleMouseEvent(void* nativeObj, cocos2d::EventMouse::MouseEventType eventType, cocos2d::Event* event, jsval* jsvalRet = nullptr); bool handleKeybardEvent(void* nativeObj, cocos2d::EventKeyboard::KeyCode keyCode, bool isPressed, cocos2d::Event* event); + + void restartVM(); }; JSObject* NewGlobalObject(JSContext* cx, bool debug = false); diff --git a/frameworks/js-bindings/bindings/script/jsb_boot.js b/frameworks/js-bindings/bindings/script/jsb_boot.js index 00de8416b3..74c28d913e 100644 --- a/frameworks/js-bindings/bindings/script/jsb_boot.js +++ b/frameworks/js-bindings/bindings/script/jsb_boot.js @@ -1327,6 +1327,12 @@ cc._initSys = function(config, CONFIG_KEY){ __restartVM(); }; + // clean a singal js file + locSys.cleanScript = function(jsFile) { + __cleanScript(jsFile); + }; + + locSys.dump = function(){ var self = this; var str = ""; @@ -1506,6 +1512,14 @@ cc.game = { config[CONFIG_KEY.frameRate] = frameRate; cc.director.setAnimationInterval(1.0/frameRate); }, + + /** + * Restart game. + */ + restart: function () { + __restartVM(); + }, + /** * Run game. */ @@ -1519,6 +1533,7 @@ cc.game = { self.onStart(); } }, + /** * Init config. * @param cb diff --git a/frameworks/js-bindings/cocos2d-x b/frameworks/js-bindings/cocos2d-x index 4e6473be00..776aadd4e2 160000 --- a/frameworks/js-bindings/cocos2d-x +++ b/frameworks/js-bindings/cocos2d-x @@ -1 +1 @@ -Subproject commit 4e6473be00c6bd44cd9be462a8b4d09de0e4c371 +Subproject commit 776aadd4e29a9beaa14ea53062d7ac8ecf923ea9 diff --git a/samples/js-moonwarriors/project/Classes/AppDelegate.cpp b/samples/js-moonwarriors/project/Classes/AppDelegate.cpp index 95a9ae66a1..08f7a7557d 100644 --- a/samples/js-moonwarriors/project/Classes/AppDelegate.cpp +++ b/samples/js-moonwarriors/project/Classes/AppDelegate.cpp @@ -4,18 +4,8 @@ #include "SimpleAudioEngine.h" #include "ScriptingCore.h" #include "jsb_cocos2dx_auto.hpp" -#include "jsb_cocos2dx_extension_auto.hpp" -#include "jsb_cocos2dx_builder_auto.hpp" -#include "extension/jsb_cocos2dx_extension_manual.h" #include "cocos2d_specifics.hpp" -#include "cocosbuilder/js_bindings_ccbreader.h" #include "localstorage/js_bindings_system_registration.h" -#include "chipmunk/js_bindings_chipmunk_registration.h" -#include "jsb_opengl_registration.h" -#include "jsb_cocos2dx_ui_auto.hpp" -#include "ui/jsb_cocos2dx_ui_manual.h" -#include "cocostudio/jsb_cocos2dx_studio_manual.h" -#include "jsb_cocos2dx_studio_auto.hpp" USING_NS_CC; using namespace CocosDenshion; @@ -26,7 +16,7 @@ AppDelegate::AppDelegate() AppDelegate::~AppDelegate() { - ScriptEngineManager::destroyInstance(); + ScriptEngineManager::destroyInstance(); } void AppDelegate::initGLContextAttrs() @@ -54,27 +44,13 @@ bool AppDelegate::applicationDidFinishLaunching() sc->addRegisterCallback(register_cocos2dx_js_core); sc->addRegisterCallback(register_cocos2dx_js_extensions); sc->addRegisterCallback(jsb_register_system); - - //sc->addRegisterCallback(register_all_cocos2dx_extension); - //sc->addRegisterCallback(register_all_cocos2dx_extension_manual); - - //sc->addRegisterCallback(jsb_register_chipmunk); - //sc->addRegisterCallback(register_all_cocos2dx_builder); - //sc->addRegisterCallback(register_CCBuilderReader); - - //sc->addRegisterCallback(JSB_register_opengl); - //sc->addRegisterCallback(register_all_cocos2dx_ui); - //sc->addRegisterCallback(register_all_cocos2dx_ui_manual); - //sc->addRegisterCallback(register_all_cocos2dx_studio); - //sc->addRegisterCallback(register_all_cocos2dx_studio_manual); - sc->start(); sc->runScript("script/jsb_boot.js"); #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0) sc->enableDebugger(); #endif - + auto pEngine = ScriptingCore::getInstance(); ScriptEngineManager::getInstance()->setScriptEngine(pEngine); @@ -90,7 +66,7 @@ void AppDelegate::applicationDidEnterBackground() director->stopAnimation(); director->getEventDispatcher()->dispatchCustomEvent("game_on_hide"); SimpleAudioEngine::getInstance()->pauseBackgroundMusic(); - SimpleAudioEngine::getInstance()->pauseAllEffects(); + SimpleAudioEngine::getInstance()->pauseAllEffects(); } // this function will be called when the app is active again diff --git a/samples/js-tests/project.json b/samples/js-tests/project.json index 36988c2b91..1ed27f831b 100644 --- a/samples/js-tests/project.json +++ b/samples/js-tests/project.json @@ -70,6 +70,7 @@ "src/EventTest/EventTest.js", "src/UnitTest/UnitTest.js", "src/SysTest/SysTest.js", + "src/SysTest/ScriptTestTempFile.js", "src/EffectsTest/EffectsTest.js", "src/EffectsAdvancedTest/EffectsAdvancedTest.js", "src/MotionStreakTest/MotionStreakTest.js", diff --git a/samples/js-tests/res/Manifests/ScriptTest/project.manifest b/samples/js-tests/res/Manifests/ScriptTest/project.manifest new file mode 100644 index 0000000000..83fb2282ef --- /dev/null +++ b/samples/js-tests/res/Manifests/ScriptTest/project.manifest @@ -0,0 +1,13 @@ +{ + "packageUrl" : "http://tools.itharbors.com/assets_manager/ScriptTest/", + "remoteManifestUrl" : "http://tools.itharbors.com/assets_manager/ScriptTest/project_dev.manifest", + "remoteVersionUrl" : "http://tools.itharbors.com/assets_manager/ScriptTest/version_dev.manifest", + "version" : "1.0.0", + "engineVersion" : "3.0", + + "assets" : { + }, + + "searchPaths" : [ + ] +} \ No newline at end of file diff --git a/samples/js-tests/src/SysTest/ScriptTestTempFile.js b/samples/js-tests/src/SysTest/ScriptTestTempFile.js new file mode 100644 index 0000000000..f9edd31553 --- /dev/null +++ b/samples/js-tests/src/SysTest/ScriptTestTempFile.js @@ -0,0 +1,38 @@ +/**************************************************************************** + Copyright (c) 2008-2010 Ricardo Quesada + Copyright (c) 2011-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. + ****************************************************************************/ + +var ScriptTestTempLayer = cc.Layer.extend({ + ctor : function () { + this._super(); + + var labelTest = new cc.LabelTTF("this is the ScriptTestTempLayer old file", "Verdana", 32, cc.size(winSize.width, 50), cc.TEXT_ALIGNMENT_CENTER); + var size = cc.winSize; + labelTest.setPosition(size.width / 2, size.height / 4); + this.addChild(labelTest); + + } + +}); diff --git a/samples/js-tests/src/SysTest/SysTest.js b/samples/js-tests/src/SysTest/SysTest.js index d772d358cc..532cbd5413 100644 --- a/samples/js-tests/src/SysTest/SysTest.js +++ b/samples/js-tests/src/SysTest/SysTest.js @@ -123,16 +123,167 @@ var SysTestScene = TestScene.extend({ } }); +//------------------------------------------------------------------ +// +// Script dynamic reload test +// +//------------------------------------------------------------------ +var tempJSFileName = "ScriptTestTempFile.js"; +var ScriptTestLayer = SysTestBase.extend({ + _tempLayer:null, + _am : null, + startDownload:function () { + if (!cc.sys.isNative) + { + return; + } + var manifestPath = "Manifests/ScriptTest/project.manifest"; + var storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : "/") + "JSBTests/AssetsManagerTest/ScriptTest/"); + cc.log("Storage path for this test : " + storagePath); + + if (this._am) + { + this._am.release(); + this._am = null; + } + + this._am = new jsb.AssetsManager(manifestPath, storagePath); + this._am.retain(); + if (!this._am.getLocalManifest().isLoaded()) + { + cc.log("Fail to update assets, step skipped."); + that.clickMeShowTempLayer(); + } + else { + var that = this; + var listener = new jsb.EventListenerAssetsManager(this._am, function (event) { + var scene; + switch (event.getEventCode()) { + case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST: + cc.log("No local manifest file found, skip assets update."); + that.clickMeShowTempLayer(); + break; + case jsb.EventAssetsManager.UPDATE_PROGRESSION: + cc.log(event.getPercent() + "%"); + break; + case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST: + case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST: + cc.log("Fail to download manifest file, update skipped."); + that.clickMeShowTempLayer(); + break; + case jsb.EventAssetsManager.ALREADY_UP_TO_DATE: + case jsb.EventAssetsManager.UPDATE_FINISHED: + cc.log("Update finished. " + event.getMessage()); + require(tempJSFileName); + that.clickMeShowTempLayer(); + break; + case jsb.EventAssetsManager.UPDATE_FAILED: + cc.log("Update failed. " + event.getMessage()); + break; + case jsb.EventAssetsManager.ERROR_UPDATING: + cc.log("Asset update error: " + event.getAssetId() + ", " + event.getMessage()); + break; + case jsb.EventAssetsManager.ERROR_DECOMPRESS: + cc.log(event.getMessage()); + break; + default: + break; + } + }); + cc.eventManager.addListener(listener, 1); + this._am.update(); + } + }, + clickMeShowTempLayer:function () { + this.removeChildByTag(233, true); + this._tempLayer = new ScriptTestTempLayer(); + this.addChild(this._tempLayer, 0, 233); + }, + clickMeReloadTempLayer:function(){ + cc.sys.cleanScript(tempJSFileName); + if (!cc.sys.isNative) + { + this.clickMeShowTempLayer(); + } + else + { + this.startDownload(); + } + + }, + onExit : function () { + if (this._am) + { + this._am.release(); + this._am = null; + } + + this._super(); + }, + ctor : function () { + this._super(); + + var menu = new cc.Menu(); + menu.setPosition(cc.p(0, 0)); + menu.width = winSize.width; + menu.height = winSize.height; + this.addChild(menu, 1); + var item1 = new cc.MenuItemLabel(new cc.LabelTTF("Click me show tempLayer", "Arial", 22), this.clickMeShowTempLayer, this); + menu.addChild(item1); + + var item2 = new cc.MenuItemLabel(new cc.LabelTTF("Click me reload tempLayer", "Arial", 22), this.clickMeReloadTempLayer, this); + menu.addChild(item2); + + menu.alignItemsVerticallyWithPadding(8); + menu.setPosition(cc.pAdd(cc.visibleRect.left, cc.p(+180, 0))); + }, + + getTitle : function() { + return "ScriptTest only used in native"; + } + +}); + +//------------------------------------------------------------------ +// +// Restart game test +// +//------------------------------------------------------------------ +var RestartGameLayerTest = SysTestBase.extend({ + getTitle : function() { + return "RestartGameTest only used in native"; + }, + restartGame:function() + { + cc.game.restart(); + }, + ctor : function () { + this._super(); + var menu = new cc.Menu(); + menu.setPosition(cc.p(0, 0)); + menu.width = winSize.width; + menu.height = winSize.height; + this.addChild(menu, 1); + var item1 = new cc.MenuItemLabel(new cc.LabelTTF("restartGame", "Arial", 22), this.restartGame, this); + menu.addChild(item1); + menu.setPosition(cc.pAdd(cc.visibleRect.left, cc.p(+180, 0))); + } +}); + // // Flow control // var arrayOfSysTest = [ - LocalStorageTest, CapabilitiesTest ]; +if (cc.sys.isNative && cc.sys.OS_WINDOWS != cc.sys.os) { + arrayOfSysTest.push(ScriptTestLayer); + arrayOfSysTest.push(RestartGameLayerTest); +} + var nextSysTest = function () { sysTestSceneIdx++; sysTestSceneIdx = sysTestSceneIdx % arrayOfSysTest.length;