image sprite partial
diff --git a/extension/CSXS/manifest.xml b/extension/CSXS/manifest.xml index f5eee37..56a8f2a 100644 --- a/extension/CSXS/manifest.xml +++ b/extension/CSXS/manifest.xml
@@ -1,13 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> -<ExtensionManifest Version="5.0" ExtensionBundleId="com.bodymovin.bodymovin" ExtensionBundleVersion="4.0.4" +<ExtensionManifest Version="6.0" ExtensionBundleId="com.bodymovin.bodymovin" ExtensionBundleVersion="4.0.4" ExtensionBundleName="bodymovin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ExtensionList> <Extension Id="com.bodymovin.bodymovin" Version="4.0.4" /> </ExtensionList> <ExecutionEnvironment> <HostList> - <Host Name="AEFT" Version="[13.0,13.9]" /> - <Host Name="AEFX" Version="[13.0,13.9]" /> + <Host Name="AEFT" Version="13.0" /> + <Host Name="AEFX" Version="13.0" /> <!-- Illustrator --> <!-- <Host Name="ILST" Version="[18.0,18.9]" />--> @@ -27,7 +27,7 @@ <Locale Code="All" /> </LocaleList> <RequiredRuntimeList> - <RequiredRuntime Name="CSXS" Version="5.0" /> + <RequiredRuntime Name="CSXS" Version="6.0" /> </RequiredRuntimeList> </ExecutionEnvironment> <DispatchInfoList> @@ -36,6 +36,11 @@ <Resources> <MainPath>./index.html</MainPath> <ScriptPath>./jsx/hostscript.jsx</ScriptPath> + <CEFCommandLine> + <Parameter>--enable-nodejs</Parameter> + <Parameter>--mixed-context</Parameter> + <Parameter>--enable-media-stream</Parameter> + </CEFCommandLine> </Resources> <Lifecycle> <AutoVisible>true</AutoVisible>
diff --git a/extension/index.html b/extension/index.html index c30d05f..00c4af9 100644 --- a/extension/index.html +++ b/extension/index.html
@@ -186,6 +186,7 @@ <script src="js/controllers/messageController.js"></script> <script src="js/controllers/InfoController.js"></script> <script src="js/utils/storage.js"></script> + <script src="js/utils/binpacking.js"></script> <script src="js/controllers/snapshotController.js"></script> <script src="js/main.js"></script>
diff --git a/extension/js/controllers/CompRenderController.js b/extension/js/controllers/CompRenderController.js index e7e2cd1..b30e191 100644 --- a/extension/js/controllers/CompRenderController.js +++ b/extension/js/controllers/CompRenderController.js
@@ -198,6 +198,17 @@ }); } + function renderAtlasHandler(ev) { + var messageData = ev.data; + bm_binpacker.reset(); + bm_binpacker.addBlocks(messageData.images); + var atlasPack = bm_binpacker.getPack(); + var atlasDataString = JSON.stringify(atlasPack); + var eScript = 'bm_renderManager.setAtlasData(' + atlasDataString + ')'; + csInterface.evalScript(eScript); + + } + function renderCharsHandler(ev) { var messageData = ev.data; var chars; @@ -272,6 +283,7 @@ csInterface.addEventListener('bm:render:complete', renderCompleteHandler); csInterface.addEventListener('bm:render:fonts', renderFontsHandler); csInterface.addEventListener('bm:render:chars', renderCharsHandler); + csInterface.addEventListener('bm:render:atlas', renderAtlasHandler); cancelButton = view.find('.cancel'); returnButton = view.find('.return');
diff --git a/extension/js/main.js b/extension/js/main.js index c653953..8e4f766 100644 --- a/extension/js/main.js +++ b/extension/js/main.js
@@ -8,10 +8,6 @@ var csInterface = new CSInterface(); var mainViews = []; - - var gulp = require('gulp'); - var gzip = require('gulp-gzip'); - function showView(view) { var i, len = mainViews.length; for (i = 0; i < len; i += 1) {
diff --git a/extension/js/utils/binpacking.js b/extension/js/utils/binpacking.js new file mode 100644 index 0000000..3abfcf3 --- /dev/null +++ b/extension/js/utils/binpacking.js
@@ -0,0 +1,43 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */ +/*global console, require*/ + +var bm_binpacker = (function () { + 'use strict'; + var ob = {}, blocks = [], packer, binpacking, GrowingPacker; + if (typeof require === 'function') { + ob.enabled = true; + binpacking = require('binpacking'); + GrowingPacker = binpacking.GrowingPacker; + } + + function addBlocks(blocks) { + console.log(blocks); + var i, len = blocks.length; + for(i = 0; i < len; i += 1) { + addBlock(blocks[i]); + } + } + + function addBlock(block) { + blocks.push(block); + } + + function getPack() { + var packer = new GrowingPacker(); + blocks.sort(function(a, b) { return (b.h > a.h); }); + packer.fit(blocks); + console.log(blocks); + return blocks; + } + + function reset() { + blocks.length = 0; + } + + ob.addBlock = addBlock; + ob.addBlocks = addBlocks; + ob.reset = reset; + ob.getPack = getPack; + + return ob; +}()); \ No newline at end of file
diff --git a/extension/jsx/renderManager.jsx b/extension/jsx/renderManager.jsx index e033ba2..aebd618 100644 --- a/extension/jsx/renderManager.jsx +++ b/extension/jsx/renderManager.jsx
@@ -107,6 +107,7 @@ function reset() { pendingLayers.length = 0; pendingComps.length = 0; + ob.renderData.exportData.assets.length = 0; currentCompSettings = null; } @@ -215,7 +216,10 @@ saveData(); } - function imagesReady() { + function imagesReady(assetsArray) { + if(assetsArray) { + ob.renderData.exportData.assets = assetsArray; + } checkFonts(); } @@ -238,6 +242,7 @@ ob.setChars = setChars; ob.imagesReady = imagesReady; ob.setFontData = setFontData; + ob.setAtlasData = bm_sourceHelper.setAtlasData; ob.setCharsData = setCharsData; ob.hasExpressions = hasExpressions;
diff --git a/extension/jsx/utils/sourceHelper.jsx b/extension/jsx/utils/sourceHelper.jsx index 3d98203..08193cc 100644 --- a/extension/jsx/utils/sourceHelper.jsx +++ b/extension/jsx/utils/sourceHelper.jsx
@@ -3,6 +3,7 @@ var bm_sourceHelper = (function () { 'use strict'; var compSources = [], imageSources = [], fonts = [], currentExportingImage, destinationPath, assetsArray, folder, helperComp, currentCompID, imageCount = 0; + var ob = {}; function checkCompSource(item) { var arr = compSources; @@ -79,6 +80,72 @@ saveNextImage(); } + function createAtlas() { + var i, len = imageSources.length; + var imagesList = []; + for (i = 0; i < len; i += 1) { + imagesList.push({ + w: imageSources[i].width + 4, + h: imageSources[i].height + 4, + id: imageSources[i].id + }); + } + bm_eventDispatcher.sendEvent('bm:render:atlas', {images: imagesList}); + } + + function getSourceDataById(id) { + var i = 0, len = imageSources.length; + while( i < len) { + if(imageSources[i].id === id) { + return imageSources[i]; + } + i += 1; + } + } + + function setAtlasData(blocks) { + if (bm_compsManager.cancelled) { + return; + } + var compWidth = 0; + var compHeight = 0; + var i, len = blocks.length; + for (i = 0; i < len; i += 1) { + compWidth = Math.max(blocks[i].fit.w + blocks[i].fit.x, compWidth); + compHeight = Math.max(blocks[i].fit.h + blocks[i].fit.y, compHeight); + } + var helperComp = app.project.items.addComp('atlasConverterComp', Math.max(4, compWidth), Math.max(4, compHeight), 1, 1, 1); + var source, sourceData, layer; + for (i = 0; i < len; i += 1) { + sourceData = getSourceDataById(blocks[i].id); + source = sourceData.source; + layer = helperComp.layers.add(source); + layer.transform['Anchor Point'].setValue([0, 0]); + layer.transform['Position'].setValue([blocks[i].fit.x + 2, blocks[i].fit.y + 2]); + assetsArray.push({ + id: blocks[i].id, + w: blocks[i].w, + h: blocks[i].h, + x: blocks[i].fit.x + 2, + y: blocks[i].fit.y + 2, + p: 'images/atlas_' + '0' + '.png' + }); + } + bm_eventDispatcher.log('assetsArray len: ' + assetsArray.length); + bm_renderManager.imagesReady(assetsArray); + var file = new File(folder.absoluteURI + '/atlas_' + '0' + '.png'); + helperComp.saveFrameToPng(0, file); + helperComp.remove(); + } + + function saveImages() { + if (ob.atlas) { + createAtlas(); + } else { + saveNextImage(); + } + } + function exportImages(path, assets, compId) { if (imageSources.length === 0) { bm_renderManager.imagesReady(); @@ -93,12 +160,12 @@ assetsArray = assets; if (!folder.exists) { if (folder.create()) { - saveNextImage(); + saveImages(); } else { bm_eventDispatcher.sendEvent('alert', 'folder failed to be created at: ' + folder.fsName); } } else { - saveNextImage(); + saveImages(); } } @@ -127,16 +194,21 @@ imageSources.length = 0; fonts.length = 0; imageCount = 0; + assetsArray = null; } - return { + ob = { checkCompSource: checkCompSource, checkImageSource: checkImageSource, setCompSourceId: setCompSourceId, + setAtlasData: setAtlasData, exportImages : exportImages, addFont : addFont, getFonts : getFonts, + atlas: true, reset: reset }; + return ob; + }()); \ No newline at end of file
diff --git a/player/index.html b/player/index.html index 137879b..26f0c17 100644 --- a/player/index.html +++ b/player/index.html
@@ -40,6 +40,7 @@ <script src="js/utils/bez.js"></script> <script src="js/utils/DataManager.js"></script> <script src="js/utils/FontManager.js"></script> + <script src="js/utils/ImageManager.js"></script> <script src="js/utils/expressions/ExpressionManager.js"></script> <script src="js/utils/expressions/ExpressionComp.js"></script> <script src="js/utils/expressions/ShapeInterface.js"></script>
diff --git a/player/js/elements/ImageElement.js b/player/js/elements/ImageElement.js index 8ffadea..3fd27a3 100644 --- a/player/js/elements/ImageElement.js +++ b/player/js/elements/ImageElement.js
@@ -10,15 +10,26 @@ var self = this; var imageLoaded = function(){ - self.innerElem.setAttributeNS('http://www.w3.org/1999/xlink','href',self.path+self.assetData.p); + var cv = document.createElement('canvas'); + cv.width = self.assetData.w; + cv.height = self.assetData.h; + var ctx = cv.getContext('2d'); + ctx.drawImage(img,self.assetData.x,self.assetData.y,self.assetData.w,self.assetData.h,0,0,self.assetData.w,self.assetData.h); + var dataUri = cv.toDataURL(); + self.innerElem.setAttributeNS('http://www.w3.org/1999/xlink','href',dataUri); + //self.innerElem.setAttributeNS('http://www.w3.org/1999/xlink','href',self.path+self.assetData.p); self.maskedElement = self.innerElem; + ImageManager.unregisterImage(imgLoader); }; - var img = new Image(); - img.addEventListener('load', imageLoaded, false); - img.addEventListener('error', imageLoaded, false); - - img.src = this.path+this.assetData.p; + var imgLoader = ImageManager.getImage(this.path+this.assetData.p); + var img = imgLoader.elem; + if(imgLoader.loaded) { + imageLoaded(); + } else { + img.addEventListener('load', imageLoaded, false); + img.addEventListener('error', imageLoaded, false); + } this.parent.createElements.call(this);
diff --git a/player/js/utils/ImageManager.js b/player/js/utils/ImageManager.js new file mode 100644 index 0000000..12cd903 --- /dev/null +++ b/player/js/utils/ImageManager.js
@@ -0,0 +1,48 @@ +var ImageManager = (function(){ + + var images = []; + var ob = {}; + + function getImage(path){ + var i = 0, len = images.length; + while(i<len) { + if(images[i].path === path){ + images[i].count += 1; + return images[i]; + } + i += 1; + } + + function imageLoaded(){ + imageOb.loaded = true; + } + + var img = document.createElement('img'); + img.addEventListener('load', imageLoaded, false); + img.addEventListener('error', imageLoaded, false); + + var imageOb = { + elem: img, + path: path, + loaded: false, + count: 1 + }; + img.src = path; + images.push(imageOb); + return imageOb; + } + + function unregisterImage(ob){ + ob.count -= 1; + if(ob.count === 0) { + var ind = images.indexOf(ob); + images.splice(ind, 1); + ob.elem = null; + } + } + + ob.getImage = getImage; + ob.unregisterImage = unregisterImage; + + return ob; +}()); \ No newline at end of file