[HTML5] Locale, input fix, context, exit.
Add missing semicolumns in engine.js Add optional extra args to JS Engine.startGame Remove loader.js, explicit noExitRuntime. Also add onExit callback (undocumented in emscripten)
This commit is contained in:
parent
6a0473bcc2
commit
ee99cd42d5
@ -32,7 +32,6 @@ env.Depends(build, js_modules)
|
||||
|
||||
engine = [
|
||||
"engine/preloader.js",
|
||||
"engine/loader.js",
|
||||
"engine/utils.js",
|
||||
"engine/engine.js",
|
||||
]
|
||||
|
@ -164,3 +164,6 @@ def configure(env):
|
||||
|
||||
# callMain for manual start, FS for preloading.
|
||||
env.Append(LINKFLAGS=["-s", 'EXTRA_EXPORTED_RUNTIME_METHODS=["callMain", "FS"]'])
|
||||
|
||||
# Add code that allow exiting runtime.
|
||||
env.Append(LINKFLAGS=['-s', 'EXIT_RUNTIME=1'])
|
||||
|
@ -1,16 +1,8 @@
|
||||
Function('return this')()['Engine'] = (function() {
|
||||
|
||||
var unloadAfterInit = true;
|
||||
var canvas = null;
|
||||
var resizeCanvasOnStart = false;
|
||||
var customLocale = 'en_US';
|
||||
var wasmExt = '.wasm';
|
||||
|
||||
var preloader = new Preloader();
|
||||
var loader = new Loader();
|
||||
var rtenv = null;
|
||||
|
||||
var executableName = '';
|
||||
var wasmExt = '.wasm';
|
||||
var unloadAfterInit = true;
|
||||
var loadPath = '';
|
||||
var loadPromise = null;
|
||||
var initPromise = null;
|
||||
@ -33,31 +25,42 @@ Function('return this')()['Engine'] = (function() {
|
||||
};
|
||||
|
||||
/** @constructor */
|
||||
function Engine() {};
|
||||
function Engine() {
|
||||
this.canvas = null;
|
||||
this.executableName = '';
|
||||
this.rtenv = null;
|
||||
this.customLocale = null;
|
||||
this.resizeCanvasOnStart = false;
|
||||
this.onExit = null;
|
||||
};
|
||||
|
||||
Engine.prototype.init = /** @param {string=} basePath */ function(basePath) {
|
||||
if (initPromise) {
|
||||
return initPromise;
|
||||
}
|
||||
if (!loadPromise) {
|
||||
if (loadPromise == null) {
|
||||
if (!basePath) {
|
||||
initPromise = Promise.reject(new Error("A base path must be provided when calling `init` and the engine is not loaded."));
|
||||
return initPromise;
|
||||
}
|
||||
load(basePath);
|
||||
}
|
||||
var config = {}
|
||||
var config = {};
|
||||
if (typeof stdout === 'function')
|
||||
config.print = stdout;
|
||||
if (typeof stderr === 'function')
|
||||
config.printErr = stderr;
|
||||
initPromise = loader.init(loadPromise, loadPath, config).then(function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
rtenv = loader.env;
|
||||
var me = this;
|
||||
initPromise = new Promise(function(resolve, reject) {
|
||||
config['locateFile'] = Utils.createLocateRewrite(loadPath);
|
||||
config['instantiateWasm'] = Utils.createInstantiatePromise(loadPromise);
|
||||
Godot(config).then(function(module) {
|
||||
me.rtenv = module;
|
||||
if (unloadAfterInit) {
|
||||
loadPromise = null;
|
||||
unload();
|
||||
}
|
||||
resolve();
|
||||
config = null;
|
||||
});
|
||||
});
|
||||
return initPromise;
|
||||
@ -76,33 +79,71 @@ Function('return this')()['Engine'] = (function() {
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
var me = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
return me.init().then(function() {
|
||||
if (!(canvas instanceof HTMLCanvasElement)) {
|
||||
canvas = Utils.findCanvas();
|
||||
}
|
||||
rtenv['locale'] = customLocale;
|
||||
rtenv['canvas'] = canvas;
|
||||
rtenv['thisProgram'] = executableName;
|
||||
rtenv['resizeCanvasOnStart'] = resizeCanvasOnStart;
|
||||
loader.start(preloader.preloadedFiles, args).then(function() {
|
||||
loader = null;
|
||||
initPromise = null;
|
||||
resolve();
|
||||
return me.init().then(function() {
|
||||
if (!me.rtenv) {
|
||||
reject(new Error('The engine must be initialized before it can be started'));
|
||||
}
|
||||
|
||||
if (!(me.canvas instanceof HTMLCanvasElement)) {
|
||||
me.canvas = Utils.findCanvas();
|
||||
}
|
||||
|
||||
// Canvas can grab focus on click, or key events won't work.
|
||||
if (me.canvas.tabIndex < 0) {
|
||||
me.canvas.tabIndex = 0;
|
||||
}
|
||||
|
||||
// Disable right-click context menu.
|
||||
me.canvas.addEventListener('contextmenu', function(ev) {
|
||||
ev.preventDefault();
|
||||
}, false);
|
||||
|
||||
// Until context restoration is implemented warn the user of context loss.
|
||||
me.canvas.addEventListener('webglcontextlost', function(ev) {
|
||||
alert("WebGL context lost, please reload the page");
|
||||
ev.preventDefault();
|
||||
}, false);
|
||||
|
||||
// Browser locale, or custom one if defined.
|
||||
var locale = me.customLocale;
|
||||
if (!locale) {
|
||||
locale = navigator.languages ? navigator.languages[0] : navigator.language;
|
||||
locale = locale.split('.')[0];
|
||||
}
|
||||
me.rtenv['locale'] = locale;
|
||||
me.rtenv['canvas'] = me.canvas;
|
||||
me.rtenv['thisProgram'] = me.executableName;
|
||||
me.rtenv['resizeCanvasOnStart'] = me.resizeCanvasOnStart;
|
||||
me.rtenv['noExitRuntime'] = true;
|
||||
me.rtenv['onExit'] = function(code) {
|
||||
if (me.onExit)
|
||||
me.onExit(code);
|
||||
me.rtenv = null;
|
||||
}
|
||||
return new Promise(function(resolve, reject) {
|
||||
preloader.preloadedFiles.forEach(function(file) {
|
||||
Utils.copyToFS(me.rtenv['FS'], file.path, file.buffer);
|
||||
});
|
||||
preloader.preloadedFiles.length = 0; // Clear memory
|
||||
me.rtenv['callMain'](args);
|
||||
initPromise = null;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Engine.prototype.startGame = function(execName, mainPack) {
|
||||
Engine.prototype.startGame = function(execName, mainPack, extraArgs) {
|
||||
// Start and init with execName as loadPath if not inited.
|
||||
executableName = execName;
|
||||
this.executableName = execName;
|
||||
var me = this;
|
||||
return Promise.all([
|
||||
this.init(execName),
|
||||
this.preloadFile(mainPack, mainPack)
|
||||
]).then(function() {
|
||||
return me.start('--main-pack', mainPack);
|
||||
var args = ['--main-pack', mainPack];
|
||||
if (extraArgs)
|
||||
args = args.concat(extraArgs);
|
||||
return me.start.apply(me, args);
|
||||
});
|
||||
};
|
||||
|
||||
@ -118,67 +159,78 @@ Function('return this')()['Engine'] = (function() {
|
||||
};
|
||||
|
||||
Engine.prototype.setCanvas = function(canvasElem) {
|
||||
canvas = canvasElem;
|
||||
this.canvas = canvasElem;
|
||||
};
|
||||
|
||||
Engine.prototype.setCanvasResizedOnStart = function(enabled) {
|
||||
resizeCanvasOnStart = enabled;
|
||||
this.resizeCanvasOnStart = enabled;
|
||||
};
|
||||
|
||||
Engine.prototype.setLocale = function(locale) {
|
||||
customLocale = locale;
|
||||
this.customLocale = locale;
|
||||
};
|
||||
|
||||
Engine.prototype.setExecutableName = function(newName) {
|
||||
executableName = newName;
|
||||
this.executableName = newName;
|
||||
};
|
||||
|
||||
Engine.prototype.setProgressFunc = function(func) {
|
||||
progressFunc = func;
|
||||
}
|
||||
};
|
||||
|
||||
Engine.prototype.setStdoutFunc = function(func) {
|
||||
|
||||
var print = function(text) {
|
||||
if (arguments.length > 1) {
|
||||
text = Array.prototype.slice.call(arguments).join(" ");
|
||||
}
|
||||
func(text);
|
||||
};
|
||||
if (rtenv)
|
||||
rtenv.print = print;
|
||||
if (this.rtenv)
|
||||
this.rtenv.print = print;
|
||||
stdout = print;
|
||||
};
|
||||
|
||||
Engine.prototype.setStderrFunc = function(func) {
|
||||
|
||||
var printErr = function(text) {
|
||||
if (arguments.length > 1)
|
||||
text = Array.prototype.slice.call(arguments).join(" ");
|
||||
func(text);
|
||||
};
|
||||
if (rtenv)
|
||||
rtenv.printErr = printErr;
|
||||
if (this.rtenv)
|
||||
this.rtenv.printErr = printErr;
|
||||
stderr = printErr;
|
||||
};
|
||||
|
||||
Engine.prototype.setOnExit = function(onExit) {
|
||||
this.onExit = onExit;
|
||||
}
|
||||
|
||||
Engine.prototype.copyToFS = function(path, buffer) {
|
||||
if (this.rtenv == null) {
|
||||
throw new Error("Engine must be inited before copying files");
|
||||
}
|
||||
Utils.copyToFS(this.rtenv['FS'], path, buffer);
|
||||
}
|
||||
|
||||
// Closure compiler exported engine methods.
|
||||
/** @export */
|
||||
Engine['isWebGLAvailable'] = Utils.isWebGLAvailable;
|
||||
Engine['load'] = load;
|
||||
Engine['unload'] = unload;
|
||||
Engine.prototype['init'] = Engine.prototype.init
|
||||
Engine.prototype['preloadFile'] = Engine.prototype.preloadFile
|
||||
Engine.prototype['start'] = Engine.prototype.start
|
||||
Engine.prototype['startGame'] = Engine.prototype.startGame
|
||||
Engine.prototype['setWebAssemblyFilenameExtension'] = Engine.prototype.setWebAssemblyFilenameExtension
|
||||
Engine.prototype['setUnloadAfterInit'] = Engine.prototype.setUnloadAfterInit
|
||||
Engine.prototype['setCanvas'] = Engine.prototype.setCanvas
|
||||
Engine.prototype['setCanvasResizedOnStart'] = Engine.prototype.setCanvasResizedOnStart
|
||||
Engine.prototype['setLocale'] = Engine.prototype.setLocale
|
||||
Engine.prototype['setExecutableName'] = Engine.prototype.setExecutableName
|
||||
Engine.prototype['setProgressFunc'] = Engine.prototype.setProgressFunc
|
||||
Engine.prototype['setStdoutFunc'] = Engine.prototype.setStdoutFunc
|
||||
Engine.prototype['setStderrFunc'] = Engine.prototype.setStderrFunc
|
||||
Engine.prototype['init'] = Engine.prototype.init;
|
||||
Engine.prototype['preloadFile'] = Engine.prototype.preloadFile;
|
||||
Engine.prototype['start'] = Engine.prototype.start;
|
||||
Engine.prototype['startGame'] = Engine.prototype.startGame;
|
||||
Engine.prototype['setWebAssemblyFilenameExtension'] = Engine.prototype.setWebAssemblyFilenameExtension;
|
||||
Engine.prototype['setUnloadAfterInit'] = Engine.prototype.setUnloadAfterInit;
|
||||
Engine.prototype['setCanvas'] = Engine.prototype.setCanvas;
|
||||
Engine.prototype['setCanvasResizedOnStart'] = Engine.prototype.setCanvasResizedOnStart;
|
||||
Engine.prototype['setLocale'] = Engine.prototype.setLocale;
|
||||
Engine.prototype['setExecutableName'] = Engine.prototype.setExecutableName;
|
||||
Engine.prototype['setProgressFunc'] = Engine.prototype.setProgressFunc;
|
||||
Engine.prototype['setStdoutFunc'] = Engine.prototype.setStdoutFunc;
|
||||
Engine.prototype['setStderrFunc'] = Engine.prototype.setStderrFunc;
|
||||
Engine.prototype['setOnExit'] = Engine.prototype.setOnExit;
|
||||
Engine.prototype['copyToFS'] = Engine.prototype.copyToFS;
|
||||
return Engine;
|
||||
})();
|
||||
|
@ -1,33 +0,0 @@
|
||||
var Loader = /** @constructor */ function() {
|
||||
|
||||
this.env = null;
|
||||
|
||||
this.init = function(loadPromise, basePath, config) {
|
||||
var me = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
var cfg = config || {};
|
||||
cfg['locateFile'] = Utils.createLocateRewrite(basePath);
|
||||
cfg['instantiateWasm'] = Utils.createInstantiatePromise(loadPromise);
|
||||
loadPromise = null;
|
||||
Godot(cfg).then(function(module) {
|
||||
me.env = module;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.start = function(preloadedFiles, args) {
|
||||
var me = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (!me.env) {
|
||||
reject(new Error('The engine must be initialized before it can be started'));
|
||||
}
|
||||
preloadedFiles.forEach(function(file) {
|
||||
Utils.copyToFS(me.env['FS'], file.path, file.buffer);
|
||||
});
|
||||
preloadedFiles.length = 0; // Clear memory
|
||||
me.env['callMain'](args);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user