diff --git a/lib/gcapi b/lib/gcapi index c52ea717..a60d0c5c 160000 --- a/lib/gcapi +++ b/lib/gcapi @@ -1 +1 @@ -Subproject commit c52ea7176fb02469fd7f937ce21efe3bb0cd21e2 +Subproject commit a60d0c5c9f9066324e860e87e1a6b439e653c5db diff --git a/lib/timestep b/lib/timestep index b829ae50..b15211a0 160000 --- a/lib/timestep +++ b/lib/timestep @@ -1 +1 @@ -Subproject commit b829ae50f3ee7f2c4f9af5b5fc23524f79d5d638 +Subproject commit b15211a0b9ebe724cc17f75d3f77332a1ad1053a diff --git a/projects/whack-that-mole b/projects/whack-that-mole index 32aed393..1721a64d 160000 --- a/projects/whack-that-mole +++ b/projects/whack-that-mole @@ -1 +1 @@ -Subproject commit 32aed39334091fe6d86247388778a712df15ea33 +Subproject commit 1721a64d9154c108b0622980fc9f630b36e42095 diff --git a/src/build/packager.js b/src/build/packager.js index e9e2186c..8e9b8a20 100644 --- a/src/build/packager.js +++ b/src/build/packager.js @@ -106,7 +106,7 @@ var CONFIG_GLOBAL_TEMPLATE = { servicesURL: null, // String noRedirect: false, // boolean inviteURLTemplate: null, // String - preload: {} // Map + splash: {} // Map }; // Return a JSON object for the global CONFIG object. @@ -149,8 +149,8 @@ function getConfigObject (project, opts, target) { logger.log("Using services URL " + config.servicesURL); - if (manifest.preload != null) { - config.preload = JSON.parse(JSON.stringify(manifest.preload)); + if (manifest.splash != null) { + config.splash = JSON.parse(JSON.stringify(manifest.splash)); } var urlOpts = { @@ -295,7 +295,6 @@ function useURISlashes (str) { return str.replace(regexSlash, '/'); } // The spriter sprites images, but also returns a list of resources. It is a // tool of many faces. function getResources(manifest, target, appDir, output, cb) { - // object on success to pass to cb(err, res); var result = {}; @@ -339,7 +338,23 @@ function getResources(manifest, target, appDir, output, cb) { }; }); + var filteredPaths = []; + result.resources = resources.other.map(function (filename) { + if (path.basename(filename) === "metadata.json") { + try { + var filedata = fs.readFileSync(path.resolve(appDir, filename), 'utf8'); + var fileobj = JSON.parse(filedata); + if (fileobj.package === false) { + var filterPath = path.dirname(filename); + logger.log("Not packaging resources from", filterPath); + filteredPaths.push(filterPath); + } + } catch (ex) { + logger.error("WARNING:", filename, "format is not valid JSON so cannot parse it."); + } + } + var ext = path.extname(filename); return { basename: path.basename(filename, ext), @@ -349,6 +364,26 @@ function getResources(manifest, target, appDir, output, cb) { }; }); + // remove paths that have metadata package:false + for (var ii = 0; ii < result.resources.length; ++ii) { + var filespec = result.resources[ii]; + var filename = filespec.relative; + + if (path.basename(filename) === "metadata.json") { + logger.log("Did not package the metadata file", filename); + result.resources.splice(ii--, 1); + continue; + } + + for (var fp in filteredPaths) { + if (filename.indexOf(filteredPaths[fp]) === 0) { + logger.log("Did not package resource", filename); + result.resources.splice(ii--, 1); + continue; + } + } + } + var mapPath = path.resolve(fullSpriteDir, resources.map); f(mapPath); fs.readFile(mapPath, 'utf8', f()); @@ -390,21 +425,29 @@ function getResources(manifest, target, appDir, output, cb) { }); } +function writeMetadata(opts, dir, json) { + var fontsDir = path.join(opts.fullPath, dir); + var fontsMetadata = path.join(fontsDir, "metadata.json"); + if (fs.existsSync(fontsDir) && fs.lstatSync(fontsDir).isDirectory() && !fs.existsSync(fontsMetadata)) { + fs.writeFileSync(fontsMetadata, json); + } +} + // Compile resources together and pass a cache object to the next function. // runs the spriter and compiles the build code. function compileResources (project, opts, target, initialImport, cb) { + logger.log("Packaging resources..."); + // Font sheets cannot be sprited; add a metadata.json file for fonts (for compatibility) - var fontsDir = path.join(opts.fullPath, "resources/fonts"); - var fontsMetadata = path.join(fontsDir, "metadata.json"); - if (fs.existsSync(fontsDir) && fs.lstatSync(fontsDir).isDirectory() && !fs.existsSync(fontsMetadata)) { - fs.writeFileSync(fontsMetadata, JSON.stringify({"sprite": false})); - } + writeMetadata(opts, "resources/fonts", '{"sprite": false}'); + writeMetadata(opts, "resources/icons", '{"sprite": false, "package": false}'); + writeMetadata(opts, "resources/splash", '{"sprite": false, "package": false}'); var f = ff(function () { getResources(project.manifest, target, opts.fullPath, opts.localBuildPath, f()); packageJS(opts, initialImport, false, f()); }, function (files, jsSrc) { - logger.log("finished packaging resources"); + logger.log("Finished packaging resources"); // merge results into a single object f({ @@ -412,11 +455,10 @@ function compileResources (project, opts, target, initialImport, cb) { jsSrc: jsSrc }) }) - .cb(cb) - .error(function (e) { - logger.error("unexpected error when packaging resources"); - console.error(e); - }); + .cb(cb) + .error(function (e) { + logger.error("ERROR: While packaging resources:", e); + }); }; /** diff --git a/src/init/templates/empty/manifest.json b/src/init/templates/empty/manifest.json index 63ff7695..53049a45 100644 --- a/src/init/templates/empty/manifest.json +++ b/src/init/templates/empty/manifest.json @@ -6,43 +6,42 @@ "supportedOrientations": [ "landscape" ], - "icons": { - "28": "preload/icons/icon28.png", - "38": "preload/icons/icon38.png", - "48": "preload/icons/icon48.png", - "56": "preload/icons/icon56.png", - "57": "preload/icons/icon57.png", - "72": "preload/icons/icon72.png", - "114": "preload/icons/icon114.png", - "144": "preload/icons/icon144.png", - "512": "preload/icons/icon512.png" - }, - "preload": { + "icon": "resources/icons/icon512.png", + "splash": { "autoHide": true, - "img": "preload/splash.png", - "iphone": { - "launch": "preload/iphone/Default.png", - "launchRetina": "preload/iphone/Default@2x.png", - "launchRetina4": "preload/iphone/Default-568h@2x.png" - }, - "ipad": { - "portrait": "preload/ipad/Default-Portrait~ipad.png", - "portraitRetina": "preload/ipad/Default-Portrait@2x~ipad.png", - "landscape": "preload/ipad/Default-Landscape~ipad.png", - "landscapeRetina": "preload/ipad/Default-Landscape@2x~ipad.png" + "scaleMethod": "cover", + "portrait480": "resources/splash/portrait480.png", + "portrait960": "resources/splash/portrait960.png", + "portrait1024": "resources/splash/portrait1024.png", + "portrait1136": "resources/splash/portrait1136.png", + "portrait2048": "resources/splash/portrait2048.png", + "landscape768": "resources/splash/landscape768.png", + "landscape1536": "resources/splash/landscape1536.png" + }, + "android": { + "versionCode": 1, + "icons": { + "36": "resources/icons/android36.png", + "48": "resources/icons/android48.png", + "72": "resources/icons/android72.png", + "96": "resources/icons/android96.png" + } + }, + "ios": { + "bundleID": "example.bundle", + "appleID": "12345678", + "version": "1.0.0", + "icons": { + "renderGloss": true, + "57": "resources/icons/ios57.png", + "72": "resources/icons/ios72.png", + "114": "resources/icons/ios114.png", + "144": "resources/icons/ios144.png" } }, "studio": { "name": "Example Studio Name", "domain": "studio.example.com", "stagingDomain": "staging.example.com" - }, - "android": { - "versionCode": 1 - }, - "ios": { - "bundleID": "example.bundle", - "appleID": "1234567", - "version": "1.0.0" } } diff --git a/src/init/templates/empty/preload/icons/icon114.png b/src/init/templates/empty/preload/icons/icon114.png deleted file mode 100644 index 6963108a..00000000 Binary files a/src/init/templates/empty/preload/icons/icon114.png and /dev/null differ diff --git a/src/init/templates/empty/preload/icons/icon144.png b/src/init/templates/empty/preload/icons/icon144.png deleted file mode 100644 index 2c14a6f5..00000000 Binary files a/src/init/templates/empty/preload/icons/icon144.png and /dev/null differ diff --git a/src/init/templates/empty/preload/icons/icon28.png b/src/init/templates/empty/preload/icons/icon28.png deleted file mode 100644 index aa0188bb..00000000 Binary files a/src/init/templates/empty/preload/icons/icon28.png and /dev/null differ diff --git a/src/init/templates/empty/preload/icons/icon38.png b/src/init/templates/empty/preload/icons/icon38.png deleted file mode 100644 index f8c30a28..00000000 Binary files a/src/init/templates/empty/preload/icons/icon38.png and /dev/null differ diff --git a/src/init/templates/empty/preload/icons/icon48.png b/src/init/templates/empty/preload/icons/icon48.png deleted file mode 100644 index 708966a1..00000000 Binary files a/src/init/templates/empty/preload/icons/icon48.png and /dev/null differ diff --git a/src/init/templates/empty/preload/icons/icon56.png b/src/init/templates/empty/preload/icons/icon56.png deleted file mode 100644 index 0ecae413..00000000 Binary files a/src/init/templates/empty/preload/icons/icon56.png and /dev/null differ diff --git a/src/init/templates/empty/preload/icons/icon57.png b/src/init/templates/empty/preload/icons/icon57.png deleted file mode 100644 index 4509daff..00000000 Binary files a/src/init/templates/empty/preload/icons/icon57.png and /dev/null differ diff --git a/src/init/templates/empty/preload/icons/icon72.png b/src/init/templates/empty/preload/icons/icon72.png deleted file mode 100644 index 6b0faab9..00000000 Binary files a/src/init/templates/empty/preload/icons/icon72.png and /dev/null differ diff --git a/src/init/templates/empty/preload/ipad/Default-Landscape@2x~ipad.png b/src/init/templates/empty/preload/ipad/Default-Landscape@2x~ipad.png deleted file mode 100644 index 9ead49fc..00000000 Binary files a/src/init/templates/empty/preload/ipad/Default-Landscape@2x~ipad.png and /dev/null differ diff --git a/src/init/templates/empty/preload/ipad/Default-Landscape~ipad.png b/src/init/templates/empty/preload/ipad/Default-Landscape~ipad.png deleted file mode 100644 index bb86b147..00000000 Binary files a/src/init/templates/empty/preload/ipad/Default-Landscape~ipad.png and /dev/null differ diff --git a/src/init/templates/empty/preload/ipad/Default-Portrait~ipad.png b/src/init/templates/empty/preload/ipad/Default-Portrait~ipad.png deleted file mode 100644 index 0736d824..00000000 Binary files a/src/init/templates/empty/preload/ipad/Default-Portrait~ipad.png and /dev/null differ diff --git a/src/init/templates/empty/preload/iphone/Default-568h@2x.png b/src/init/templates/empty/preload/iphone/Default-568h@2x.png deleted file mode 100644 index 364e2587..00000000 Binary files a/src/init/templates/empty/preload/iphone/Default-568h@2x.png and /dev/null differ diff --git a/src/init/templates/empty/preload/iphone/Default.png b/src/init/templates/empty/preload/iphone/Default.png deleted file mode 100644 index 77294d3c..00000000 Binary files a/src/init/templates/empty/preload/iphone/Default.png and /dev/null differ diff --git a/src/init/templates/empty/preload/iphone/Default@2x.png b/src/init/templates/empty/preload/iphone/Default@2x.png deleted file mode 100644 index ec816296..00000000 Binary files a/src/init/templates/empty/preload/iphone/Default@2x.png and /dev/null differ diff --git a/src/init/templates/empty/preload/splash.png b/src/init/templates/empty/preload/splash.png deleted file mode 100644 index d6d0feff..00000000 Binary files a/src/init/templates/empty/preload/splash.png and /dev/null differ diff --git a/src/init/templates/empty/resources/icons/android36.png b/src/init/templates/empty/resources/icons/android36.png new file mode 100644 index 00000000..b5664e7d Binary files /dev/null and b/src/init/templates/empty/resources/icons/android36.png differ diff --git a/src/init/templates/empty/resources/icons/android48.png b/src/init/templates/empty/resources/icons/android48.png new file mode 100644 index 00000000..2e0bd344 Binary files /dev/null and b/src/init/templates/empty/resources/icons/android48.png differ diff --git a/src/init/templates/empty/resources/icons/android72.png b/src/init/templates/empty/resources/icons/android72.png new file mode 100644 index 00000000..e4151a0b Binary files /dev/null and b/src/init/templates/empty/resources/icons/android72.png differ diff --git a/src/init/templates/empty/resources/icons/android96.png b/src/init/templates/empty/resources/icons/android96.png new file mode 100644 index 00000000..7e1cbb7d Binary files /dev/null and b/src/init/templates/empty/resources/icons/android96.png differ diff --git a/src/init/templates/empty/preload/icons/icon512.png b/src/init/templates/empty/resources/icons/icon512.png similarity index 100% rename from src/init/templates/empty/preload/icons/icon512.png rename to src/init/templates/empty/resources/icons/icon512.png diff --git a/src/init/templates/empty/resources/icons/ios114.png b/src/init/templates/empty/resources/icons/ios114.png new file mode 100644 index 00000000..62fd756c Binary files /dev/null and b/src/init/templates/empty/resources/icons/ios114.png differ diff --git a/src/init/templates/empty/resources/icons/ios144.png b/src/init/templates/empty/resources/icons/ios144.png new file mode 100644 index 00000000..b3a99d24 Binary files /dev/null and b/src/init/templates/empty/resources/icons/ios144.png differ diff --git a/src/init/templates/empty/resources/icons/ios57.png b/src/init/templates/empty/resources/icons/ios57.png new file mode 100644 index 00000000..d1dafc62 Binary files /dev/null and b/src/init/templates/empty/resources/icons/ios57.png differ diff --git a/src/init/templates/empty/resources/icons/ios72.png b/src/init/templates/empty/resources/icons/ios72.png new file mode 100644 index 00000000..8b544963 Binary files /dev/null and b/src/init/templates/empty/resources/icons/ios72.png differ diff --git a/src/init/templates/empty/resources/splash/README.txt b/src/init/templates/empty/resources/splash/README.txt new file mode 100644 index 00000000..859267ab --- /dev/null +++ b/src/init/templates/empty/resources/splash/README.txt @@ -0,0 +1,28 @@ +Your game must incorporate the Game Closure logo provided in the GC DevKit +(or another logo expressly made available to you by Game Closure) (“Logo”) +in the following manner: + ++ The Logo must be unmodified. + ++ The Logo must conform to any instructions or directives provided with the + splash screen source, including but not limited to directives on the duration + of exposure, timing of exposure, pixel density, aspect ratio, and overall + quality of presentation. + ++ Unless otherwise specified, the Logo must be displayed for 3 seconds at full + resolution and maximum quality allowed by the phone. + ++ The Logo must not be stretched or skewed, but the background content may be + truncated in the case that the Logo does not exactly fit the aspect ratio of + the physical device. + ++ The Logo must be shown before any menu is displayed or user input is received + and processed by the game. + + +Subject to the terms of conditions of this Agreement and any guidelines that +may be provided or updated by Game Closure from time to time, Game Closure +hereby grants you a non-exclusive, revocable, worldwide, non-sublicesable, +nontransferable right to use the Logo solely in accordance with the foregoing +guidelines. + diff --git a/src/init/templates/empty/resources/splash/landscape1536.png b/src/init/templates/empty/resources/splash/landscape1536.png new file mode 100644 index 00000000..dff9dfff Binary files /dev/null and b/src/init/templates/empty/resources/splash/landscape1536.png differ diff --git a/src/init/templates/empty/resources/splash/landscape768.png b/src/init/templates/empty/resources/splash/landscape768.png new file mode 100644 index 00000000..34c8de08 Binary files /dev/null and b/src/init/templates/empty/resources/splash/landscape768.png differ diff --git a/src/init/templates/empty/resources/splash/portrait1024.png b/src/init/templates/empty/resources/splash/portrait1024.png new file mode 100644 index 00000000..5c37c62f Binary files /dev/null and b/src/init/templates/empty/resources/splash/portrait1024.png differ diff --git a/src/init/templates/empty/resources/splash/portrait1136.png b/src/init/templates/empty/resources/splash/portrait1136.png new file mode 100644 index 00000000..558b5b1b Binary files /dev/null and b/src/init/templates/empty/resources/splash/portrait1136.png differ diff --git a/src/init/templates/empty/preload/ipad/Default-Portrait@2x~ipad.png b/src/init/templates/empty/resources/splash/portrait2048.png similarity index 100% rename from src/init/templates/empty/preload/ipad/Default-Portrait@2x~ipad.png rename to src/init/templates/empty/resources/splash/portrait2048.png diff --git a/src/init/templates/empty/resources/splash/portrait480.png b/src/init/templates/empty/resources/splash/portrait480.png new file mode 100644 index 00000000..7b01a348 Binary files /dev/null and b/src/init/templates/empty/resources/splash/portrait480.png differ diff --git a/src/init/templates/empty/resources/splash/portrait960.png b/src/init/templates/empty/resources/splash/portrait960.png new file mode 100644 index 00000000..810e74b3 Binary files /dev/null and b/src/init/templates/empty/resources/splash/portrait960.png differ diff --git a/src/init/templates/stackview/manifest.json b/src/init/templates/stackview/manifest.json index 896748ef..46200cd5 100644 --- a/src/init/templates/stackview/manifest.json +++ b/src/init/templates/stackview/manifest.json @@ -1,13 +1,46 @@ { - "title": "StackView Template", - "icons": { - "128": "resources/images/icon.png" + "appID": "stackviewtemplate", + "shortName": "stackview", + "title": "Stack View Template", + "studio": { + "name": "Lil' Varmit Studios", + "domain": "lilvarmit.com", + "stagingDomain": "staging.lilvarmit.com" }, "supportedOrientations": [ "portrait" ], - "preload": { + "icon": "resources/icons/icon512.png", + "splash": { "autoHide": true, - "img": "resources/images/splash.png" - } + "scaleMethod": "cover", + "portrait480": "resources/splash/portrait480.png", + "portrait960": "resources/splash/portrait960.png", + "portrait1024": "resources/splash/portrait1024.png", + "portrait1136": "resources/splash/portrait1136.png", + "portrait2048": "resources/splash/portrait2048.png", + "landscape768": "resources/splash/landscape768.png", + "landscape1536": "resources/splash/landscape1536.png" + }, + "android": { + "versionCode": 1, + "icons": { + "36": "resources/icons/android36.png", + "48": "resources/icons/android48.png", + "72": "resources/icons/android72.png", + "96": "resources/icons/android96.png" + } + }, + "ios": { + "bundleID": "whackamole", + "appleID": "123456789", + "version": "1.0.0", + "icons": { + "57": "resources/icons/ios57.png", + "72": "resources/icons/ios72.png", + "114": "resources/icons/ios114.png", + "144": "resources/icons/ios144.png", + "renderGloss": true + } + }, } diff --git a/src/serve/plugins/projects/static/Pane.js b/src/serve/plugins/projects/static/Pane.js index 78b6dcae..643069a4 100644 --- a/src/serve/plugins/projects/static/Pane.js +++ b/src/serve/plugins/projects/static/Pane.js @@ -42,7 +42,7 @@ var ProjectCell = Class(squill.Cell, function() { var defaultIcon = '/images/defaultIcon.png'; this.icon.style.backgroundImage = 'url(' + (project.getIcon(512) || defaultIcon) + ')'; - if (project.manifest.icons.renderGloss) { + if (project.manifest.ios && project.manifest.ios.icons && project.manifest.ios.icons.renderGloss) { $.addClass(this.icon, 'gloss'); } else { $.removeClass(this.icon, 'gloss'); diff --git a/src/serve/plugins/simulate/plugin.js b/src/serve/plugins/simulate/plugin.js index 9fd78384..177a860d 100644 --- a/src/serve/plugins/simulate/plugin.js +++ b/src/serve/plugins/simulate/plugin.js @@ -125,13 +125,49 @@ exports.load = function (app, argv) { } }); - app.get('/simulate/:shortName/:target/loading.png', function (req, res, next) { + app.get('/simulate/:shortName/:target/splash/:splash', function (req, res, next) { var projects = common.getProjectList(); var project = projects[req.params.shortName]; + var splash = req.params.splash; - var img = project && project.manifest.preload && project.manifest.preload.img; + var img = project && project.manifest.splash && project.manifest.splash[splash]; if (!img) { - return next(); + //if the key does not exist in the manifest we need to generate one + var splashSizes = { + "portrait480": "320x480", + "portrait960": "640x960", + "portrait1024": "768x1024", + "portrait1136": "640x1136", + "portrait2048": "1536x2048", + "landscape768": "1024x768", + "landscape1536": "2048x1496" + }; + var outSize = splashSizes[splash]; + if (project.manifest.splash && project.manifest.splash["universal"] && outSize) { + //run the splasher to generate a splash of the desired size + logger.log("Splash image mapped from universal ->", splash); + var outImg = path.join(project.paths.root,".tempsplash.png"); + build.jvmtools.exec('splasher', [ + "-i", path.resolve(project.paths.root, project.manifest.splash["universal"]), + "-o", outImg, + "-resize", outSize, + "-rotate", "auto" + ], function (splasher) { + var formatter = new build.common.Formatter('splasher'); + splasher.on('out', formatter.out); + splasher.on('err', formatter.err); + splasher.on('end', function (data) { + var stream = fs.createReadStream(outImg); + stream.pipe(res) + stream.on('end', function () { + //remove out remporary file + fs.unlinkSync(outImg); + }); + }) + }); + } else { + return next(); + } } else { img = path.resolve(project.paths.root, img); var f = ff(function () { @@ -140,6 +176,7 @@ exports.load = function (app, argv) { if (!exists) { next(); } else { + logger.log("Splash image mapped from", splash, "->", img); fs.createReadStream(img).pipe(res); } }).error(next); diff --git a/src/serve/plugins/simulate/static/util/Simulator.js b/src/serve/plugins/simulate/static/util/Simulator.js index 6229351a..eabb410e 100644 --- a/src/serve/plugins/simulate/static/util/Simulator.js +++ b/src/serve/plugins/simulate/static/util/Simulator.js @@ -146,7 +146,7 @@ var Chrome = exports = Class(squill.Widget, function (supr) { this.global.ACCESSIBILITY.mute(this.isMuted()); }); - this.global.CONFIG.preload.hide = bind(this, 'hideLoadingImage'); + this.global.CONFIG.splash.hide = bind(this, 'hideLoadingImage'); // update muted state this.mute(this._isMuted); @@ -292,7 +292,15 @@ var Chrome = exports = Class(squill.Widget, function (supr) { }; this.getLoadingImageURL = function () { - return new std.uri(this._params.target + '/loading.png').toString(); + var splash; + if (this._rotation % 2 == 0) { + //even amounts of rotations mean portrait + splash = "/splash/portrait2048"; + } else { + //oods mean landscape + splash = "/splash/landscape1536"; + } + return new std.uri(this._params.target + splash).toString(); }; this.rebuild = function (next) { diff --git a/src/serve/public/Overview.js b/src/serve/public/Overview.js index b566d464..8087a3a8 100644 --- a/src/serve/public/Overview.js +++ b/src/serve/public/Overview.js @@ -349,7 +349,7 @@ exports = Class(squill.TabbedPane, function(supr) { this._overviewProjectIcon.style.backgroundImage = "url(" + (project.getIcon(512) || "/images/defaultIcon.png") + ")"; this.simulateButton.setLabel(project.manifest.launchTitle || "Simulate"); - if (project.manifest.icons.renderGloss) { + if (project.manifest.ios && project.manifest.ios.icons && project.manifest.ios.icons.renderGloss) { $.addClass(this._overviewProjectIcon, "gloss"); } else { $.removeClass(this._overviewProjectIcon, "gloss"); diff --git a/src/serve/public/Project.js b/src/serve/public/Project.js index 1e7ad6ef..070e2ae6 100644 --- a/src/serve/public/Project.js +++ b/src/serve/public/Project.js @@ -183,8 +183,7 @@ exports = Class(function() { * Utility functions. */ - this.getIcon = function (targetSize) { - var iconList = this.manifest.icons; + this.tryIcons = function(iconList, targetSize) { var sizes = [], closest = null; if (iconList) { for (var size in iconList) { @@ -204,6 +203,21 @@ exports = Class(function() { return '/projects/' + this.id + '/files/' + iconList[sizes.pop()]; } } - return '/images/defaultIcon.png'; + + return null; + } + + this.getIcon = function (targetSize) { + var path = this.manifest.icon ? ('/projects/' + this.id + '/files/' + this.manifest.icon) : null; + if (!path) { + path = this.tryIcons(this.manifest.android && this.manifest.android.icons, targetSize); + } + if (!path) { + path = this.tryIcons(this.manifest.ios && this.manifest.ios.icons, targetSize); + } + if (!path) { + path = '/images/defaultIcon.png'; + } + return path; }; });