/**
* @fileOverview
* Defines UnityObject2
*/
//TODO: No need to polute the global space, just transfer this control to a 'static' variable insite unityObject!
/**
* @namespace
*/
//var unity = unity || {};
// We store all unityObject instances in a global scope, needed for IE firstFrameCallback and other internal tasks.
//unity.instances = [];
//unity.instanceNumber = 0;
/**
* Object expected by the Java Installer. We can move those to UnityObject2 if we update the java Installer.
*/
var unityObject = {
/**
* Callback used bt the Java installer to notify the Install Complete.
* @private
* @param {String} id
* @param {bool} success
* @param {String} errormessage
*/
javaInstallDone : function (id, success, errormessage) {
var instanceId = parseInt(id.substring(id.lastIndexOf('_') + 1), 10);
if (!isNaN(instanceId)) {
// javaInstallDoneCallback must not be called directly because it deadlocks google chrome
setTimeout(function () {
UnityObject2.instances[instanceId].javaInstallDoneCallback(id, success, errormessage);
}, 10);
}
}
};
/**
* @class
* @constructor
*/
var UnityObject2 = function (config) {
/** @private */
var logHistory = [],
win = window,
doc = document,
nav = navigator,
instanceNumber = null,
//domLoaded = false,
//domLoadEvents = [],
embeddedObjects = [], //Could be removed?
//listeners = [],
//styleSheet = null,
//styleSheetMedia = null,
//autoHideShow = true,
//fullSizeMissing = true,
useSSL = (document.location.protocol == 'https:'), //This will turn off enableUnityAnalytics, since enableUnityAnalytics don't have a https version.
baseDomain = useSSL ? "https://ssl-webplayer.unity3d.com/" : "http://webplayer.unity3d.com/",
triedJavaCookie = "_unity_triedjava",
triedJavaInstall = _getCookie(triedJavaCookie),
triedClickOnceCookie = "_unity_triedclickonce",
triedClickOnce = _getCookie(triedClickOnceCookie),
progressCallback = false,
applets = [],
//addedClickOnce = false,
googleAnalyticsLoaded = false,
googleAnalyticsCallback = null,
latestStatus = null,
lastType = null,
//beginCallback = [],
//preCallback = [],
imagesToWaitFor = [],
//referrer = null,
pluginStatus = null,
pluginStatusHistory = [],
installProcessStarted = false, //not used anymore?
kInstalled = "installed",
kMissing = "missing",
kBroken = "broken",
kUnsupported = "unsupported",
kReady = "ready", //not used anymore?
kStart = "start",
kError = "error",
kFirst = "first",
//kStandard = "standard",
kJava = "java",
kClickOnce = "clickonce", //not used anymore?
wasMissing = false, //identifies if this is a install attempt, or if the plugin was already installed
unityObject = null, //The <embed> or <object> for the webplayer. This can be used for webPlayer communication.
//kApplet = "_applet",
//kBanner = "_banner",
cfg = {
pluginName : "Unity Player",
pluginMimeType : "application/vnd.unity",
baseDownloadUrl : baseDomain + "download_webplayer-3.x/",
fullInstall : false,
autoInstall : false,
enableJava : true,
enableJVMPreloading : false,
enableClickOnce : true,
enableUnityAnalytics : false,
enableGoogleAnalytics : true,
params : {},
attributes : {},
referrer : null,
debugLevel : 0
};
// Merge in the given configuration and override defaults.
cfg = jQuery.extend(true, cfg, config);
if (cfg.referrer === "") {
cfg.referrer = null;
}
//enableUnityAnalytics does not support SSL yet.
if (useSSL) {
cfg.enableUnityAnalytics = false;
}
/**
* Get cookie value
* @private
* @param {String} name The param name
* @return string or false if non-existing.
*/
function _getCookie(name) {
var e = new RegExp(escape(name) + "=([^;]+)");
if (e.test(doc.cookie + ";")) {
e.exec(doc.cookie + ";");
return RegExp.$1;
}
return false;
}
/**
* Sets session cookie
* @private
*/
function _setSessionCookie(name, value) {
document.cookie = escape(name) + "=" + escape(value) + "; path=/";
}
/**
* Converts unity version to number (used for version comparison)
* @private
*/
function _getNumericUnityVersion(version) {
var result = 0,
major,
minor,
fix,
type,
release;
if (version) {
var m = version.toLowerCase().match(/^(\d+)(?:\.(\d+)(?:\.(\d+)([dabfr])?(\d+)?)?)?$/);
if (m && m[1]) {
major = m[1];
minor = m[2] ? m[2] : 0;
fix = m[3] ? m[3] : 0;
type = m[4] ? m[4] : 'r';
release = m[5] ? m[5] : 0;
result |= ((major / 10) % 10) << 28;
result |= (major % 10) << 24;
result |= (minor % 10) << 20;
result |= (fix % 10) << 16;
result |= {d: 2 << 12, a: 4 << 12, b: 6 << 12, f: 8 << 12, r: 8 << 12}[type];
result |= ((release / 100) % 10) << 8;
result |= ((release / 10) % 10) << 4;
result |= (release % 10);
}
}
return result;
}
/**
* Gets plugin and unity versions (non-ie)
* @private
*/
function _getPluginVersion(callback, versions) {
var b = doc.getElementsByTagName("body")[0];
var ue = doc.createElement("object");
var i = 0;
if (b && ue) {
ue.setAttribute("type", cfg.pluginMimeType);
ue.style.visibility = "hidden";
b.appendChild(ue);
var count = 0;
(function () {
if (typeof ue.GetPluginVersion === "undefined") {
if (count++ < 10) {
setTimeout(arguments.callee, 10);
} else {
b.removeChild(ue);
callback(null);
}
} else {
var v = {};
if (versions) {
for (i = 0; i < versions.length; ++i) {
v[versions] = ue.GetUnityVersion(versions);
}
}
v.plugin = ue.GetPluginVersion();
b.removeChild(ue);
callback(v);
}
})();
} else {
callback(null);
}
}
/**
* Retrieves windows installer name
* @private
*/
function _getWinInstall() {
var url = cfg.fullInstall ? "UnityWebPlayerFull.exe" : "UnityWebPlayer.exe";
if (cfg.referrer !== null) {
url += "?referrer=" + cfg.referrer;
}
return url;
}
/**
* Retrieves mac plugin package name
* @private
*/
function _getOSXInstall() {
var url = "UnityPlayer.plugin.zip";
if (cfg.referrer != null) {
url += "?referrer=" + cfg.referrer;
}
return url;
}
/**
* retrieves installer name
* @private
*/
function _getInstaller() {
return cfg.baseDownloadUrl + (ua.win ? _getWinInstall() : _getOSXInstall() );
}
/**
* sets plugin status
* @private
*/
function _setPluginStatus(status, type, data, url) {
if (status === kMissing){
wasMissing = true;
}
// debug('setPluginStatus() status:', status, 'type:', type, 'data:', data, 'url:', url);
// only report to analytics the first time a status occurs.
if ( jQuery.inArray(status, pluginStatusHistory) === -1 ) {
//Only send analytics for plugins installs. Do not send if plugin is already installed.
if (wasMissing) {
_an.send(status, type, data, url);
}
pluginStatusHistory.push(status);
}
pluginStatus = status;
}
/**
* Contains browser and platform properties
* @private
*/
var ua = function () {
var a = nav.userAgent, p = nav.platform;
var chrome = /chrome/i.test(a);
var ua = {
w3 : typeof doc.getElementById != "undefined" && typeof doc.getElementsByTagName != "undefined" && typeof doc.createElement != "undefined",
win : p ? /win/i.test(p) : /win/i.test(a),
mac : p ? /mac/i.test(p) : /mac/i.test(a),
ie : /msie/i.test(a) ? parseFloat(a.replace(/^.*msie ([0-9]+(\.[0-9]+)?).*$/i, "$1")) : false,
ff : /firefox/i.test(a),
op : /opera/i.test(a),
ch : chrome,
ch_v : /chrome/i.test(a) ? parseFloat(a.replace(/^.*chrome\/(\d+(\.\d+)?).*$/i, "$1")) : false,
sf : /safari/i.test(a) && !chrome,
wk : /webkit/i.test(a) ? parseFloat(a.replace(/^.*webkit\/(\d+(\.\d+)?).*$/i, "$1")) : false,
x64 : /win64/i.test(a) && /x64/i.test(a),
moz : /mozilla/i.test(a) ? parseFloat(a.replace(/^.*mozilla\/([0-9]+(\.[0-9]+)?).*$/i, "$1")) : 0,
mobile: /ipad/i.test(p) || /iphone/i.test(p) || /ipod/i.test(p) || /android/i.test(a) || /windows phone/i.test(a)
};
ua.clientBrand = ua.ch ? 'ch' : ua.ff ? 'ff' : ua.sf ? 'sf' : ua.ie ? 'ie' : ua.op ? 'op' : '??';
ua.clientPlatform = ua.win ? 'win' : ua.mac ? 'mac' : '???';
// get base url
var s = doc.getElementsByTagName("script");
for (var i = 0; i < s.length; ++i) {
var m = s.src.match(/^(.*)3\.0\/uo\/UnityObject2\.js$/i);
if (m) {
cfg.baseDownloadUrl = m[1];
break;
}
}
/**
* compares two versions
* @private
*/
function _compareVersions(v1, v2) {
for (var i = 0; i < Math.max(v1.length, v2.length); ++i) {
var n1 = (i < v1.length) && v1 ? new Number(v1) : 0;
var n2 = (i < v2.length) && v2 ? new Number(v2) : 0;
if (n1 < n2) return -1;
if (n1 > n2) return 1;
}
return 0;
};
/**
* detect java
*/
ua.java = function () {
if (nav.javaEnabled()) {
var wj = (ua.win && ua.ff);
var mj = false;//(ua.mac && (ua.ff || ua.ch || ua.sf));
if (wj || mj) {
if (typeof nav.mimeTypes != "undefined") {
var rv = wj ? [1, 6, 0, 12] : [1, 4, 2, 0];
for (var i = 0; i < nav.mimeTypes.length; ++i) {
if (nav.mimeTypes.enabledPlugin) {
var m = nav.mimeTypes.type.match(/^application\/x-java-applet;(?:jpi-)?version=(\d+)(?:\.(\d+)(?:\.(\d+)(?:_(\d+))?)?)?$/);
if (m != null) {
if (_compareVersions(rv, m.slice(1)) <= 0) {
return true;
}
}
}
}
}
} else if (ua.win && ua.ie) {
if (typeof ActiveXObject != "undefined") {
/**
* ActiveX Test
*/
function _axTest(v) {
try {
return new ActiveXObject("JavaWebStart.isInstalled." + v + ".0") != null;
}
catch (ex) {
return false;
}
}
/**
* ActiveX Test 2
*/
function _axTest2(v) {
try {
return new ActiveXObject("JavaPlugin.160_" + v) != null;
} catch (ex) {
return false;
}
}
if (_axTest("1.7.0")) {
return true;
}
if (ua.ie >= 8) {
if (_axTest("1.6.0")) {
// make sure it's 1.6.0.12 or newer. increment 50 to a larger value if 1.6.0.50 is released
for (var i = 12; i <= 50; ++i) {
if (_axTest2(i)) {
if (ua.ie == 9 && ua.moz == 5 && i < 24) {
// when IE9 is not in compatibility mode require at least
// Java 1.6.0.24: http://support.microsoft.com/kb/2506617
continue;
} else {
return true;
}
}
}
return false;
}
} else {
return _axTest("1.6.0") || _axTest("1.5.0") || _axTest("1.4.2");
}
}
}
}
return false;
}();
// detect clickonce
ua.co = function () {
if (ua.win && ua.ie) {
var av = a.match(/(\.NET CLR [0-9.]+)|(\.NET[0-9.]+)/g);
if (av != null) {
var rv = [3, 5, 0];
for (var i = 0; i < av.length; ++i) {
var versionNumbers = av.match(/[0-9.]{2,}/g)[0].split(".");
if (_compareVersions(rv, versionNumbers) <= 0) {
return true;
}
}
}
}
return false;
}();
return ua;
}();
/**
* analytics
* @private
*/
var _an = function () {
var uid = function () {
var now = new Date();
var utc = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDay(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), now.getUTCMilliseconds());
return utc.toString(16) + _getRandomInt().toString(16);
}();
var seq = 0;
var _ugaq = window["_gaq"] = ( window["_gaq"] || [] );
_setUpAnalytics();
/**
* generates random integer number
* @private
*/
function _getRandomInt() {
return Math.floor(Math.random() * 2147483647);
}
/**
* Checks if there is a need to load analytics, by checking the existance of a _gaq object
*/
function _setUpAnalytics() {
var gaUrl = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var ss = doc.getElementsByTagName("script");
var googleAnalyticsLoaded = false;
for (var i = 0; i < ss.length; ++i) {
if (ss.src && ss.src.toLowerCase() == gaUrl.toLowerCase()) {
googleAnalyticsLoaded = true;
break;
}
}
if (!googleAnalyticsLoaded) {
var ga = doc.createElement("script");
ga.type = "text/javascript";
ga.async = true;
ga.src = gaUrl;
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(ga, s);
}
var gaAccount = (cfg.debugLevel === 0) ? 'UA-16068464-16' : 'UA-16068464-17';
_ugaq.push(["unity._setDomainName", "none"]);
_ugaq.push(["unity._setAllowLinker", true]);
_ugaq.push(["unity._setReferrerOverride", ' '+this.location.toString()]);
_ugaq.push(["unity._setAccount", gaAccount]);
// $(GoogleRevisionPlaceholder)
}
/**
* sends analytics data to unity
* @private
*/
function _sendUnityAnalytics(event, type, data, callback) {
if (!cfg.enableUnityAnalytics) {
if (callback) {
callback();
}
return;
}
var url = "http://unityanalyticscapture.appspot.com/event?u=" + encodeURIComponent(uid) + "&s=" + encodeURIComponent(seq) + "&e=" + encodeURIComponent(event);
// $(UnityRevisionPlaceholder)
if (cfg.referrer !== null) {
url += "?r=" + cfg.referrer;
}
if (type) {
url += "&t=" + encodeURIComponent(type);
}
if (data) {
url += "&d=" + encodeURIComponent(data);
}
var img = new Image();
if (callback) {
img.onload = img.onerror = callback;
}
img.src = url;
}
/**
* sends analytics data to google
* @private
*/
function _sendGoogleAnalytics(event, type, data, callback) {
if (!cfg.enableGoogleAnalytics) {
if (callback) {
callback();
}
return;
}
var url = "/webplayer/install/" + event;
var join = "?";
if (type) {
url += join + "t=" + encodeURIComponent(type);
join = "&";
}
if (data) {
url += join + "d=" + encodeURIComponent(data);
join = "&";
}
if (callback) {
_ugaq.push(function () {
setTimeout(callback,1000);
//this.googleAnalyticsCallback = callback;
});
}
//try to shorten the URL to fit into customVariable
//it will try to replace the early directories to ..
var gameUrl = cfg.src;
if (gameUrl.length > 40) {
gameUrl = gameUrl.replace("http://","");
var paths = gameUrl.split("/");
var gameUrlFirst = paths.shift();
var gameUrlLast = paths.pop();
gameUrl = gameUrlFirst + "/../"+ gameUrlLast;
while(gameUrl.length < 40 && paths.length > 0) {
var nextpath = paths.pop();
if(gameUrl.length + nextpath.length + 5 < 40) {
gameUrlLast = nextpath + "/" + gameUrlLast;
} else {
gameUrlLast = "../" + gameUrlLast;
}
gameUrl = gameUrlFirst + "/../"+ gameUrlLast;
}
}
_ugaq.push(['unity._setCustomVar',
2, // This custom var is set to slot #1. Required parameter.
'GameURL', // The name acts as a kind of category for the user activity. Required parameter.
gameUrl, // This value of the custom variable. Required parameter.
3 // Sets the scope to page-level. Optional parameter.
]);
_ugaq.push(['unity._setCustomVar',
1, // This custom var is set to slot #1. Required parameter.
'UnityObjectVersion', // The name acts as a kind of category for the user activity. Required parameter.
"2", // This value of the custom variable. Required parameter.
3 // Sets the scope to page-level. Optional parameter.
]);
if (type) {
_ugaq.push(['unity._setCustomVar',
3, // This custom var is set to slot #1. Required parameter.
'installMethod', // The name acts as a kind of category for the user activity. Required parameter.
type, // This value of the custom variable. Required parameter.
3 // Sets the scope to page-level. Optional parameter.
]);
}
_ugaq.push(["unity._trackPageview", url]);
}
return {
/**
* sends analytics data. optionally opens url once data has been sent
* @public
*/
send : function (event, type, data, url) {
if (cfg.enableUnityAnalytics || cfg.enableGoogleAnalytics) {
debug('Analytics SEND', event, type, data, url);
}
++seq;
var count = 2;
var callback = function () {
if (0 == --count) {
googleAnalyticsCallback = null;
window.location = url;
}
}
if (data === null || data === undefined) {
data = "";
}
_sendUnityAnalytics(event, type, data, url ? callback : null);
_sendGoogleAnalytics(event, type, data, url ? callback : null);
}
};
}();
/* Java Install - BEGIN */
/**
* @private
*/
function _createObjectElement(attributes, params, elementToReplace) {
var i,
at,
pt,
ue,
pe;
if (ua.win && ua.ie) {
at = "";
for (i in attributes) {
at += ' ' + i + '="' + attributes + '"';
}
pt = "";
for (i in params) {
pt += '<param name="' + i + '" value="' + params + '" />';
}
elementToReplace.outerHTML = '<object' + at + '>' + pt + '</object>';
} else {
ue = doc.createElement("object");
for (i in attributes) {
ue.setAttribute(i, attributes);
}
for (i in params) {
pe = doc.createElement("param");
pe.name = i;
pe.value = params;
ue.appendChild(pe);
}
elementToReplace.parentNode.replaceChild(ue, elementToReplace);
}
}
/**
* @private
*/
function _checkImage(img) {
// img element not in the DOM yet
if (typeof img == "undefined") {
return false;
}
if (!img.complete) {
return false;
}
// some browsers always return true in img.complete, for those
// we can check naturalWidth
if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) {
return false;
}
// no other way of checking, assuming it is ok
return true;
}
/**
* @private
*/
function _preloadJVMWhenReady(id) {
var needToWait = false;
for (var i = 0; i < imagesToWaitFor.length; i++) {
if (!imagesToWaitFor) {
continue;
}
var img = doc.images[imagesToWaitFor];
if (!_checkImage(img)) {
needToWait = true;
}
else {
imagesToWaitFor = null;
}
}
if (needToWait) {
// check again in 100ms
setTimeout(arguments.callee, 100);
}
else {
// preload after a small delay, to make sure
// the images have actually rendered
setTimeout(function () {
_preloadJVM(id);
}, 100);
}
}
/**
* preloads the JVM and the Java Plug-in
* @private
*/
function _preloadJVM(id) {
var re = doc.getElementById(id);
if (!re) {
re = doc.createElement("div");
var lastBodyElem = doc.body.lastChild;
doc.body.insertBefore(re, lastBodyElem.nextSibling);
}
var codebase = cfg.baseDownloadUrl + "3.0/jws/";
var a = {
id : id,
type : "application/x-java-applet",
code : "JVMPreloader",
width : 1,
height : 1,
name : "JVM Preloader"
};
var p = {
context : id,
codebase : codebase,
classloader_cache : false,
scriptable : true,
mayscript : true
};
_createObjectElement(a, p, re);
jQuery('#' + id).show();
//setVisibility(id, true);
}
/**
* launches java installer
* @private
*/
function _doJavaInstall(id) {
triedJavaInstall = true;
_setSessionCookie(triedJavaCookie, triedJavaInstall);
var re = doc.getElementById(id);
var appletID = id + "_applet_" + instanceNumber;
applets[appletID] = {
attributes : cfg.attributes,
params : cfg.params,
callback : cfg.callback,
broken : cfg.broken
};
var applet = applets[appletID];
var a = {
id : appletID,
type : "application/x-java-applet",
archive : cfg.baseDownloadUrl + "3.0/jws/UnityWebPlayer.jar",
code : "UnityWebPlayer",
width : 1,
height : 1,
name : "Unity Web Player"
};
if (ua.win && ua.ff) {
a["style"] = "visibility: hidden;";
}
var p = {
context : appletID,
jnlp_href : cfg.baseDownloadUrl + "3.0/jws/UnityWebPlayer.jnlp",
classloader_cache : false,
installer : _getInstaller(),
image : baseDomain + "installation/unitylogo.png",
centerimage : true,
boxborder : false,
scriptable : true,
mayscript : true
};
for (var i in applet.params) {
if (i == "src") {
continue;
}
if (applet.params != Object.prototype) {
p = applet.params;
if (i.toLowerCase() == "logoimage") {
p["image"] = applet.params;
}
else if (i.toLowerCase() == "backgroundcolor") {
p["boxbgcolor"] = "#" + applet.params;
}
else if (i.toLowerCase() == "bordercolor") {
// there's no way to specify border color
p["boxborder"] = true;
}
else if (i.toLowerCase() == "textcolor") {
p["boxfgcolor"] = "#" + applet.params;
}
}
}
// Create a dummy div element in the unityPlayer div
// so that it can be replaced with the 1x1 px applet.
// The applet will be resized when it has fully loaded,
// see appletStarted().
var divToBeReplacedWithApplet = doc.createElement("div");
re.appendChild(divToBeReplacedWithApplet);
_createObjectElement(a, p, divToBeReplacedWithApplet);
jQuery('#' + id).show();
//setVisibility(appletID, true);
}
/**
* @private
*/
function _jvmPreloaded(id) {
// timeout prevents crash on ie
setTimeout(function () {
var re = doc.getElementById(id);
if (re) {
re.parentNode.removeChild(re);
}
}, 0);
}
/**
* @private
*/
function _appletStarted(id) {
// set the size of the applet to the one from cloned attributes
var applet = applets[id],
appletElement = doc.getElementById(id),
childNode;
// the applet might have already finished by now
if (!appletElement) {
return;
}
appletElement.width = applet.attributes["width"] || 600;
appletElement.height = applet.attributes["height"] || 450;
// remove all the siblings of the applet
var parentNode = appletElement.parentNode;
var childNodeList = parentNode.childNodes;
for (var i = 0; i < childNodeList.length; i++) {
childNode = childNodeList;
// Compare the child node with our applet element only if
// it has the same type. Doing the comparison in other cases just
// jumps out of the loop.
if (childNode.nodeType == 1 && childNode != appletElement) {
parentNode.removeChild(childNode);
}
}
}
// java installation callback
function _javaInstallDoneCallback(id, success, errormessage) {
debug('_javaInstallDoneCallback', id, success, errormessage);
//console.log('javaInstallDoneCallback', id, success, errormessage);
if (!success) {
//var applet = applets[id];
_setPluginStatus(kError, kJava, errormessage);
//createMissingUnity(id, applet.attributes, applet.params, applet.callback, applet.broken, kJava, errormessage);
}
}
/* Java Install - END */
/**
* @private
*/
function log() {
logHistory.push(arguments);
if ( cfg.debugLevel > 0 && window.console && window.console.log ) {
console.log(Array.prototype.slice.call(arguments));
//console.log.apply(console, Array.prototype.slice.call(arguments));
}
}
/**
* @private
*/
function debug() {
logHistory.push(arguments);
if ( cfg.debugLevel > 1 && window.console && window.console.log ) {
console.log(Array.prototype.slice.call(arguments));
//console.log.apply(console, Array.prototype.slice.call(arguments));
}
}
/**
* appends px to the value if it's a plain number
* @private
*/
function _appendPX(value) {
if (/^[-+]?[0-9]+$/.test(value)) {
value += "px";
}
return value;
}
var publicAPI = /** @lends UnityObject2.prototype */ {
/**
* Get Debug Level (0=Disabled)
* @public
* @return {Number} Debug Level
*/
getLogHistory: function () {
return logHistory; // JSON.stringify()
},
/**
* Get configuration object
* @public
* @return {Object} cfg
*/
getConfig: function () {
return cfg; // JSON.stringify()
},
/**
* @public
* @return {Object} detailed info about OS and Browser.
*/
getPlatformInfo: function () {
return ua;
},
/**
* Initialize plugin config and proceed with attempting to start the webplayer.
* @public
*/
initPlugin: function (targetEl, src) {
cfg.targetEl = targetEl;
cfg.src = src;
debug('ua:', ua);
//console.debug('initPlugin this:', this);
this.detectUnity(this.handlePluginStatus);
},
/**
* detects unity web player.
* @public
* callback - accepts two parameters.
* first one contains "installed", "missing", "broken" or "unsupported" value.
* second one returns requested unity versions. plugin version is included as well.
* versions - optional array of unity versions to detect.
*/
detectUnity: function (callback, versions) {
// console.debug('detectUnity this:', this);
var self = this;
var status = kMissing;
var data;
nav.plugins.refresh();
if (ua.clientBrand === "??" || ua.clientPlatform === "???" || ua.mobile ) {
status = kUnsupported;
} else if (ua.op && ua.mac) { // Opera on MAC is unsupported
status = kUnsupported;
data = "OPERA-MAC";
} else if (
typeof nav.plugins != "undefined"
&& nav.plugins[cfg.pluginName]
&& typeof nav.mimeTypes != "undefined"
&& nav.mimeTypes[cfg.pluginMimeType]
&& nav.mimeTypes[cfg.pluginMimeType].enabledPlugin
) {
status = kInstalled;
// make sure web player is compatible with 64-bit safari
if (ua.sf && /Mac OS X 10_6/.test(nav.appVersion)) {
_getPluginVersion(function (version) {
if (!version || !version.plugin) {
status = kBroken;
data = "OSX10.6-SFx64";
}
_setPluginStatus(status, lastType, data);
callback.call(self, status, version);
}, versions);
return;
} else if (ua.mac && ua.ch) { // older versions have issues on chrome
_getPluginVersion(function (version) {
if (version && (_getNumericUnityVersion(version.plugin) <= _getNumericUnityVersion("2.6.1f3"))) {
status = kBroken;
data = "OSX-CH-U<=2.6.1f3";
}
_setPluginStatus(status, lastType, data);
callback.call(self, status, version);
}, versions);
return;
} else if (versions) {
_getPluginVersion(function (version) {
_setPluginStatus(status, lastType, data);
callback.call(self, status, version);
}, versions);
return;
}
} else if (typeof win.ActiveXObject != "undefined") {
try {
var uo = new ActiveXObject("UnityWebPlayer.UnityWebPlayer.1");
var pv = uo.GetPluginVersion();
if (versions) {
var v = {};
for (var i = 0; i < versions.length; ++i) {
v[versions] = uo.GetUnityVersion(versions);
}
v.plugin = pv;
}
status = kInstalled;
// 2.5.0 auto update has issues on vista and later
if (pv == "2.5.0f5") {
var m = /Windows NT \d+\.\d+/.exec(nav.userAgent);
if (m && m.length > 0) {
var wv = parseFloat(m[0].split(' ')[2]);
if (wv >= 6) {
status = kBroken;
data = "WIN-U2.5.0f5";
}
}
}
} catch (ex) {
if (ua.win && ua.ie && ua.x64) {
status = kUnsupported;
data = "WIN-IEx64";
}
}
}
_setPluginStatus(status, lastType, data);
callback.call(self, status, v);
},
/**
* @public
* @return {Object} with info about Unity WebPlayer plugin status (not installed, loading, running etc..)
*/
handlePluginStatus: function (status, versions) {
// Store targetEl in the closure, to be able to get it back if setTimeout calls again.
var targetEl = cfg.targetEl;
var $targetEl = jQuery(targetEl);
switch(status) {
case kInstalled:
// @todo add support for alternate custom handlers.
this.notifyProgress($targetEl);
this.embedPlugin($targetEl, cfg.callback);
break;
case kMissing:
this.notifyProgress($targetEl);
//this.installPlugin($targetEl);
var self = this;
var delayTime = (cfg.debugLevel === 0) ? 1000 : 8000;
// Do a delay and re-check for plugin
setTimeout(function () {
cfg.targetEl = targetEl;
self.detectUnity(self.handlePluginStatus);
}, delayTime);
break;
case kBroken:
// Browser needs to restart after install
this.notifyProgress($targetEl);
break;
case kUnsupported:
this.notifyProgress($targetEl);
break;
}
},
/**
* @public
* @return {Object} with detailed plugin info, version number and other info that can be retrieved from the plugin.
*/
/*getPluginInfo: function () {
},*/
/**
* @public
*/
getPluginURL: function () {
var url = "http://unity3d.com/webplayer/";
if (ua.win) {
url = cfg.baseDownloadUrl + _getWinInstall();
} else if (nav.platform == "MacIntel") {
url = cfg.baseDownloadUrl + (cfg.fullInstall ? "webplayer-i386.dmg" : "webplayer-mini.dmg");
if (cfg.referrer !== null) {
url += "?referrer=" + cfg.referrer;
}
} else if (nav.platform == "MacPPC") {
url = cfg.baseDownloadUrl + (cfg.fullInstall ? "webplayer-ppc.dmg" : "webplayer-mini.dmg");
if (cfg.referrer !== null) {
url += "?referrer=" + cfg.referrer;
}
}
return url;
},
/**
* @public
*/
getClickOnceURL: function () {
return cfg.baseDownloadUrl + "3.0/co/UnityWebPlayer.application?installer=" + encodeURIComponent(cfg.baseDownloadUrl + _getWinInstall());
},
/**
* Embed the plugin into the DOM.
* @public
*/
embedPlugin: function (targetEl, callback) {
targetEl = jQuery(targetEl).empty();
var src = cfg.src; //targetEl.data('src'),
var width = cfg.width || "100%"; //TODO: extract those hardcoded values
var height = cfg.height || "100%";
var self = this;
if (ua.win && ua.ie) {
// ie, dom and object element do not mix & match
var at = "";
for (var i in cfg.attributes) {
if (cfg.attributes != Object.prototype) {
if (i.toLowerCase() == "styleclass") {
at += ' class="' + cfg.attributes + '"';
}
else if (i.toLowerCase() != "classid") {
at += ' ' + i + '="' + cfg.attributes + '"';
}
}
}
var pt = "";
// we manually add SRC here, because its now defined on the target element.
pt += '<param name="src" value="' + src + '" />';
pt += '<param name="firstFrameCallback" value="UnityObject2.instances[' + instanceNumber + '].firstFrameCallback();" />';
for (var i in cfg.params) {
if (cfg.params != Object.prototype) {
if (i.toLowerCase() != "classid") {
pt += '<param name="' + i + '" value="' + cfg.params + '" />';
}
}
}
//var tmpHtml = '<div id="' + targetEl.attr('id') + '" style="width: ' + _appendPX(width) + '; height: ' + _appendPX(height) + ';"><object classid="clsid:444785F1-DE89-4295-863A-D46C3A781394" style="display: block; width: 100%; height: 100%;"' + at + '>' + pt + '</object></div>';
var tmpHtml = '<object classid="clsid:444785F1-DE89-4295-863A-D46C3A781394" style="display: block; width: ' + _appendPX(width) + '; height: ' + _appendPX(height) + ';"' + at + '>' + pt + '</object>';
var $object = jQuery(tmpHtml);
targetEl.append( $object );
embeddedObjects.push( targetEl.attr('id') );
unityObject = $object[0];
} else {
// Create and append embed element into DOM.
var $embed = jQuery('<embed/>')
.attr({
src: src,
type: cfg.pluginMimeType,
width: width,
height: height,
firstFrameCallback: 'UnityObject2.instances[' + instanceNumber + '].firstFrameCallback();'
})
.attr(cfg.attributes)
.attr(cfg.params)
.css({
display: 'block',
width: _appendPX(width),
height: _appendPX(height)
})
.appendTo( targetEl );
unityObject = $embed[0];
}
//Auto focus the new object/embed, so players dont have to click it before using it.
//setTimeout is here to workaround a chrome bug.
//we should not invoke focus on safari on mac. it causes some Input bugs.
if (!ua.sf || !ua.mac) {
setTimeout(function() {
unityObject.focus();
}, 100);
}
if (callback) {
callback();
}
},
/**
* Determine which installation method to use on the current platform, and return an array with their identifiers (i.e. 'ClickOnceIE', 'JavaInstall', 'Manual')
* Take into account which previous methods might have been attempted (and failed) and skip to next best method.
* @public
* @return {String}
*/
getBestInstallMethod: function () {
// Always fall back to good old manual (download) install.
var method = 'Manual';
// Is Java available and not yet attempted?
if (cfg.enableJava && ua.java && triedJavaInstall === false) {
method = 'JavaInstall';
}
// Is ClickOnce available and not yet attempted?
else if (cfg.enableClickOnce && ua.co && triedClickOnce === false) {
method = 'ClickOnceIE';
}
return method;
},
/**
* Tries to install the plugin using the specified method.
* If no method is passed, it will try to use this.getBestInstallMethod()
* @public
* @param {String} method The desired install method
*/
installPlugin: function(method) {
if (method == null || method == undefined) {
method = this.getBestInstallMethod();
}
var urlToOpen = null;
switch(method) {
case "JavaInstall":
this.doJavaInstall(cfg.targetEl.id);
break;
case "ClickOnceIE":
//urlToOpen = this.getClickOnceURL();
//window.location = urlToOpen;
var $iframe = jQuery("<iframe src='" + this.getClickOnceURL() + "' style='display:none;' />");
jQuery(cfg.targetEl).append($iframe);
break;
default:
case "Manual":
//doc.location = this.getPluginURL();
//urlToOpen = this.getPluginURL();
var $iframe = jQuery("<iframe src='" + this.getPluginURL() + "' style='display:none;' />");
jQuery(cfg.targetEl).append($iframe);
break;
}
lastType = method;
_an.send(kStart, method, null, null);
},
/**
* Trigger event using jQuery(document).trigger()
* @public
*/
//TODO: verify its use.
trigger: function (event, params) {
if (params) {
debug('trigger("' + event + '")', params);
} else {
debug('trigger("' + event + '")');
}
jQuery(document).trigger(event, params);
},
/**
* Notify observers about onProgress event
* @public
*/
notifyProgress: function (targetEl) {
//debug('*** notifyProgress ***')
if (typeof progressCallback !== "undefined" && typeof progressCallback === "function") {
var payload = {
ua: ua,
pluginStatus: pluginStatus,
bestMethod: null,
lastType: lastType,
targetEl: cfg.targetEl,
unityObj: this
};
if (pluginStatus === kMissing) {
payload.bestMethod = this.getBestInstallMethod();
}
if (latestStatus !== pluginStatus) { //Execute only on state change
latestStatus = pluginStatus;
progressCallback(payload);
}
}
},
/**
* Subscribe to onProgress notification
* @public
*/
observeProgress: function (callback) {
progressCallback = callback;
},
/**
* Callback made by the WebPlayer plugin when the first frame is rendered.
* @public
*/
firstFrameCallback : function () {
debug('*** firstFrameCallback (' + instanceNumber + ') ***');
pluginStatus = kFirst;
this.notifyProgress();
/*
// What?
if (status == kFirst) {
if (pluginStatus == null) {
return;
}
}
*/
//Webplayer was already installed.
//Should only log firstframes if it happened after a install.
if (wasMissing === true) {
_an.send(pluginStatus, lastType);
}
//setRunStatus(kFirst, lastType);
},
/**
* Get a string from a session cookie or SessionStorage
* @public
* @return {String}
*/
/*getSessionString: function (key) {
},*/
/**
* Set a string via a session cookie or SessionStorage
* @public
*/
/* setSessionString: function (key, value) {
},*/
/**
* Get a string from a persistent cookie
* @public
* @return {String}
*/
/*getCookie: function (key) {
},*/
/**
* Set a string to a persistent cookie
* @public
*/
/*setCookie: function (key, value, expiryDate) {
},*/
/**
* Exposed private function
* @public
*/
setPluginStatus: function (status, type, data, url) {
_setPluginStatus(status, type, data, url);
},
/**
* Exposed private function
* @public
*/
doJavaInstall : function (id) {
_doJavaInstall(id);
},
/**
* Exposed private function
* @public
*/
jvmPreloaded : function (id) {
_jvmPreloaded(id);
},
/**
* Exposed private function
* @public
*/
appletStarted : function (id) {
_appletStarted(id);
},
/**
* Exposed private function
* @public
*/
javaInstallDoneCallback : function (id, success, errormessage) {
_javaInstallDoneCallback(id, success, errormessage);
},
getUnity: function() {
return unityObject;
}
}
// Internal store of each instance.
instanceNumber = UnityObject2.instances.length;
UnityObject2.instances.push(publicAPI);
return publicAPI;
};
/**
* @static
**/
UnityObject2.instances = [];这是我发布的文件码, |