├── Version_Execad ├── AppName.txt ├── AppTitle.txt ├── AppID.txt ├── PresetsFolderName.txt ├── SettingsLayerName.txt └── Presets │ └── ExecAd Standard Export.seprops ├── Version_Standard ├── AppName.txt ├── AppTitle.txt ├── AppID.txt ├── SettingsLayerName.txt ├── PresetsFolderName.txt └── Presets │ └── Android Icons - Launcher (From 512x512).seprops ├── SmartCore ├── icons │ ├── eye.png │ ├── cross.png │ ├── null.png │ ├── tick.png │ ├── export.png │ ├── import.png │ ├── upArrow.png │ ├── downArrow.png │ ├── leftArrow.png │ ├── rightArrow.png │ ├── dropdownArrow.png │ ├── checkbox_disabled.png │ ├── checkbox_selected.png │ └── checkbox_unselected.png ├── Constants.jsx ├── closure.jsx ├── ExportItem.jsx ├── ExportBundle.jsx ├── DocCloser.jsx ├── ImportDialog.jsx ├── FileFilter.jsx ├── NumberControl.jsx ├── RangeControl.jsx ├── Tokens.jsx ├── SettingsPanel.jsx ├── StringControl.jsx ├── ExportDialog.jsx ├── ExportPanel.jsx ├── SaveSettingsDialog.jsx ├── FilePatternControl.jsx ├── PreviewFilesPanel.jsx ├── Queue.jsx ├── SymbolPanel.jsx ├── TabbedPanel.jsx ├── ArtboardPanel.jsx ├── MainTabbedPanel.jsx ├── MarginControl.jsx ├── Button.jsx ├── ColorPicker.jsx ├── LayerPanel.jsx ├── FormatSettings.jsx ├── SymbolBundler.jsx ├── PresetPanel.jsx ├── ArtboardBundler.jsx ├── Exporter.jsx ├── Dropdown.jsx ├── PropertiesPanel.jsx ├── ElementPanel.jsx ├── ExportSettings.jsx ├── LayerBundler.jsx ├── ExportToolBuilder.jsx └── DocUtils.jsx ├── assets ├── ExtensionIcon.ai ├── FeaturedImage.ai ├── Layer-22x22.png ├── Layer-30x30.png ├── Layer-60x60.png ├── Symbol-22x22.png ├── Symbol-30x30.png ├── Symbol-60x60.png ├── FeaturedImage.jpg ├── FeaturedImage.png ├── Layer-512x512.jpg └── OutputStateIcons.ai ├── .gitignore ├── .debug ├── html ├── panel.html └── previous.html ├── Templates └── {AppTitle}.jsx ├── manifest.xml └── README.md /Version_Execad/AppName.txt: -------------------------------------------------------------------------------- 1 | ExecAdExport -------------------------------------------------------------------------------- /Version_Execad/AppTitle.txt: -------------------------------------------------------------------------------- 1 | ExecAd Exporter -------------------------------------------------------------------------------- /Version_Standard/AppName.txt: -------------------------------------------------------------------------------- 1 | SmartExport -------------------------------------------------------------------------------- /Version_Standard/AppTitle.txt: -------------------------------------------------------------------------------- 1 | Smart Export -------------------------------------------------------------------------------- /Version_Execad/AppID.txt: -------------------------------------------------------------------------------- 1 | org.tbyrne.ExecAdExport -------------------------------------------------------------------------------- /Version_Standard/AppID.txt: -------------------------------------------------------------------------------- 1 | org.tbyrne.smartExport -------------------------------------------------------------------------------- /Version_Standard/SettingsLayerName.txt: -------------------------------------------------------------------------------- 1 | Export Settings -------------------------------------------------------------------------------- /Version_Execad/PresetsFolderName.txt: -------------------------------------------------------------------------------- 1 | ExecAd Export Presets -------------------------------------------------------------------------------- /Version_Execad/SettingsLayerName.txt: -------------------------------------------------------------------------------- 1 | ExecAd Export Settings -------------------------------------------------------------------------------- /Version_Standard/PresetsFolderName.txt: -------------------------------------------------------------------------------- 1 | Smart Export Presets -------------------------------------------------------------------------------- /SmartCore/icons/eye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/eye.png -------------------------------------------------------------------------------- /assets/ExtensionIcon.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/ExtensionIcon.ai -------------------------------------------------------------------------------- /assets/FeaturedImage.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/FeaturedImage.ai -------------------------------------------------------------------------------- /assets/Layer-22x22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/Layer-22x22.png -------------------------------------------------------------------------------- /assets/Layer-30x30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/Layer-30x30.png -------------------------------------------------------------------------------- /assets/Layer-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/Layer-60x60.png -------------------------------------------------------------------------------- /assets/Symbol-22x22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/Symbol-22x22.png -------------------------------------------------------------------------------- /assets/Symbol-30x30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/Symbol-30x30.png -------------------------------------------------------------------------------- /assets/Symbol-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/Symbol-60x60.png -------------------------------------------------------------------------------- /SmartCore/icons/cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/cross.png -------------------------------------------------------------------------------- /SmartCore/icons/null.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/null.png -------------------------------------------------------------------------------- /SmartCore/icons/tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/tick.png -------------------------------------------------------------------------------- /assets/FeaturedImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/FeaturedImage.jpg -------------------------------------------------------------------------------- /assets/FeaturedImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/FeaturedImage.png -------------------------------------------------------------------------------- /assets/Layer-512x512.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/Layer-512x512.jpg -------------------------------------------------------------------------------- /SmartCore/icons/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/export.png -------------------------------------------------------------------------------- /SmartCore/icons/import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/import.png -------------------------------------------------------------------------------- /SmartCore/icons/upArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/upArrow.png -------------------------------------------------------------------------------- /assets/OutputStateIcons.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/assets/OutputStateIcons.ai -------------------------------------------------------------------------------- /SmartCore/icons/downArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/downArrow.png -------------------------------------------------------------------------------- /SmartCore/icons/leftArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/leftArrow.png -------------------------------------------------------------------------------- /SmartCore/icons/rightArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/rightArrow.png -------------------------------------------------------------------------------- /SmartCore/icons/dropdownArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/dropdownArrow.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /ignore 2 | /build/signingtoolkit 3 | /build/cert.ppk 4 | /build/cert.p12 5 | /bin 6 | /build/password.txt 7 | /build/tools 8 | -------------------------------------------------------------------------------- /SmartCore/icons/checkbox_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/checkbox_disabled.png -------------------------------------------------------------------------------- /SmartCore/icons/checkbox_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/checkbox_selected.png -------------------------------------------------------------------------------- /SmartCore/icons/checkbox_unselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomByrne/IllustratorSmartExport/HEAD/SmartCore/icons/checkbox_unselected.png -------------------------------------------------------------------------------- /SmartCore/Constants.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | var BoundsMode = {}; 3 | 4 | BoundsMode.ARTBOARD = "artboard"; 5 | BoundsMode.ARTWORK = "artwork"; 6 | BoundsMode.ARTBOARD_AND_ARTWORK = "artboardAndArtwork"; 7 | 8 | pack.BoundsMode = BoundsMode; 9 | 10 | })(smartExport) -------------------------------------------------------------------------------- /.debug: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /SmartCore/closure.jsx: -------------------------------------------------------------------------------- 1 | closure = function(scope, meth, args, passArgs, passMethod){ 2 | if(passArgs){ 3 | var ret = function(){ 4 | var args2 = Array.prototype.slice.call(arguments); 5 | return meth.apply(scope, args2.concat(args)); 6 | } 7 | }else{ 8 | if(!args) args = []; 9 | var ret = function(){ 10 | return meth.apply(scope, args); 11 | } 12 | } 13 | if(passMethod){ 14 | if(!args)args = [ret]; 15 | else args.push(ret); 16 | } 17 | return ret; 18 | } -------------------------------------------------------------------------------- /SmartCore/ExportItem.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function ExportItem(formatSettings, fileName){ 3 | this.init(formatSettings, fileName); 4 | return this; 5 | } 6 | 7 | ExportItem.prototype={ 8 | 9 | state:"waiting", 10 | formatSettings:null, 11 | fileName:null, 12 | names:null, 13 | 14 | init:function(formatSettings, fileName){ 15 | this.names = []; 16 | this.formatSettings = formatSettings; 17 | this.fileName = fileName; 18 | } 19 | }; 20 | pack.ExportItem = ExportItem; 21 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/ExportBundle.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function ExportBundle(prepareHandler, cleanupHandler){ 3 | this.init(prepareHandler, cleanupHandler); 4 | return this; 5 | } 6 | 7 | ExportBundle.prototype={ 8 | items:null, 9 | prepareHandler:null, 10 | cleanupHandler:null, 11 | 12 | init:function(prepareHandler, cleanupHandler){ 13 | this.items = []; 14 | this.prepareHandler = prepareHandler; 15 | this.cleanupHandler = cleanupHandler; 16 | } 17 | }; 18 | pack.ExportBundle = ExportBundle; 19 | })(smartExport) -------------------------------------------------------------------------------- /html/panel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /html/previous.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SmartCore/DocCloser.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | var DocCloser = {}; 3 | 4 | DocCloser.setMainDoc = function(doc){ 5 | DocCloser.mainDoc = doc; 6 | } 7 | 8 | DocCloser.closePending = function(){ 9 | //alert("close: "+DocCloser.pendingClose); 10 | if(DocCloser.pendingClose){ 11 | DocCloser.pendingClose.close(SaveOptions.DONOTSAVECHANGES); 12 | DocCloser.pendingClose = null; 13 | } 14 | } 15 | 16 | DocCloser.closeDocument = function(doc){ 17 | DocCloser.closePending(); 18 | DocCloser.pendingClose = doc; 19 | app.activeDocument = DocCloser.mainDoc; 20 | } 21 | 22 | pack.DocCloser = DocCloser; 23 | 24 | })(smartExport) -------------------------------------------------------------------------------- /Version_Execad/Presets/ExecAd Standard Export.seprops: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 0 6 | true 7 | 8 | true 9 | true 10 | true 11 | 12 | 13 | 14 | EPS 15 | false 16 | true 17 | artwork 18 | 19 | high 20 | true 21 | 22 | <DocName>_<LayerName>.<Ext> 23 | <DocName>_proof.<Ext> 24 | <SymbolName>.<Ext> 25 | <ArtboardName>_<ElementName>.<Ext> 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /SmartCore/ImportDialog.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function ImportDialog(){ 3 | this.init(); 4 | return this; 5 | } 6 | ImportDialog.prototype={ 7 | 8 | controls:null, 9 | 10 | init:function(){ 11 | var scopedThis = this; 12 | 13 | this.dialog = new Window('dialog', "Where to Import?"); 14 | this.dialog.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 15 | 16 | this.dialog.add("statictext", undefined, "Import settings into presets or into current settings?"); 17 | 18 | 19 | 20 | var buttonRow = this.dialog.add("group"); 21 | buttonRow.orientation = "row"; 22 | buttonRow.alignment = [ScriptUI.Alignment.CENTER, ScriptUI.Alignment.TOP]; 23 | 24 | this.presetButton = buttonRow.add('button', undefined, 'Presets'); 25 | this.presetButton.onClick = function() { 26 | scopedThis.dest = "presets"; 27 | scopedThis.dialog.close(); 28 | }; 29 | 30 | this.saveButton = buttonRow.add('button', undefined, 'Current', {name:'ok'}); 31 | this.saveButton.onClick = function() { 32 | scopedThis.dest = "current"; 33 | scopedThis.dialog.close(); 34 | }; 35 | 36 | this.dialog.show(); 37 | } 38 | }; 39 | pack.ImportDialog = ImportDialog; 40 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/FileFilter.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function FileFilter(fileTypes, optimistic){ 3 | this.init(fileTypes, optimistic); 4 | return this; 5 | } 6 | 7 | 8 | 9 | FileFilter.prototype={ 10 | onChange:null, 11 | 12 | init:function(fileTypes, optimistic){ 13 | 14 | this.fileTypes = fileTypes; 15 | this.optimistic = optimistic; 16 | 17 | this.filterStr = ""; 18 | this.allowedExt = {}; 19 | for(var i=0; i this.max)value = this.max; 42 | this.value = value; 43 | this.input.text = value+this.unit; 44 | this.slider.value = value; 45 | if(onChange)onChange(); 46 | }, 47 | 48 | getValue : function(){ 49 | return this.value; 50 | } 51 | }; 52 | pack.RangeControl = RangeControl; 53 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/Tokens.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | tokens = {}; 3 | 4 | var heading = "--Tokens--"; 5 | 6 | tokens.ARTBOARD_NUM_TOKEN = ""; 7 | tokens.ARTBOARD_NAME_TOKEN = ""; 8 | 9 | tokens.LAYER_NUM_TOKEN = "", 10 | tokens.LAYER_NAME_TOKEN = ""; 11 | 12 | tokens.ELEMENT_PATH_TOKEN = "", 13 | tokens.ELEMENT_NAME_TOKEN = ""; 14 | 15 | tokens.SYMBOL_NAME_TOKEN = ""; 16 | 17 | tokens.FILE_EXT_TOKEN = ""; 18 | 19 | tokens.DOC_NAME_TOKEN = ""; 20 | 21 | tokens.ARTBOARD_TOKENS = [ heading, 22 | tokens.ARTBOARD_NUM_TOKEN, 23 | tokens.ARTBOARD_NAME_TOKEN, 24 | tokens.FILE_EXT_TOKEN, 25 | tokens.DOC_NAME_TOKEN 26 | ]; 27 | 28 | tokens.LAYER_TOKENS = [ heading, 29 | tokens.ARTBOARD_NUM_TOKEN, 30 | tokens.ARTBOARD_NAME_TOKEN, 31 | tokens.LAYER_NUM_TOKEN, 32 | tokens.LAYER_NAME_TOKEN, 33 | tokens.FILE_EXT_TOKEN, 34 | tokens.DOC_NAME_TOKEN 35 | ]; 36 | 37 | tokens.ELEMENT_TOKENS = [ heading, 38 | tokens.ARTBOARD_NUM_TOKEN, 39 | tokens.ARTBOARD_NAME_TOKEN, 40 | tokens.LAYER_NUM_TOKEN, 41 | tokens.LAYER_NAME_TOKEN, 42 | tokens.ELEMENT_PATH_TOKEN, 43 | tokens.ELEMENT_NAME_TOKEN, 44 | tokens.FILE_EXT_TOKEN, 45 | tokens.DOC_NAME_TOKEN 46 | ]; 47 | 48 | tokens.SYMBOL_TOKENS = [ heading, 49 | tokens.SYMBOL_NAME_TOKEN, 50 | tokens.FILE_EXT_TOKEN, 51 | tokens.DOC_NAME_TOKEN 52 | ]; 53 | 54 | pack.tokens = tokens; 55 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/SettingsPanel.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function SettingsPanel(container, exportSettings){ 3 | this.init(container, exportSettings); 4 | return this; 5 | } 6 | 7 | SettingsPanel.prototype={ 8 | onPatternChanged:null, 9 | onScalingChanged:null, 10 | onDirectoryChanged:null, 11 | 12 | init:function(container, exportSettings){ 13 | var scopedThis = this; 14 | this.exportSettings = exportSettings; 15 | 16 | var row; 17 | var column = container.add('group') 18 | column.orientation = 'column'; 19 | column.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 20 | 21 | // DIR GROUP 22 | row = column.add( 'group', undefined, '') 23 | row.orientation = 'row' 24 | row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP] 25 | 26 | var chooseBtn = row.add('button', undefined, 'Output Directory...' ); 27 | chooseBtn.onClick = function() { 28 | var file = new Folder(scopedThis.exportSettings.directory).selectDlg(); 29 | if(!file)return; 30 | 31 | scopedThis.directoryInput.text = file.fsName; 32 | scopedThis.directoryInput.onChange(); 33 | } 34 | 35 | this.directoryInput = row.add('edittext', undefined, exportSettings.directory); 36 | this.directoryInput.size = [ 440,20 ]; 37 | this.directoryInput.onChange = function(){ 38 | scopedThis.exportSettings.directory = scopedThis.directoryInput.text; 39 | if(scopedThis.onDirectoryChanged)scopedThis.onDirectoryChanged(); 40 | } 41 | }, 42 | 43 | updateSettings:function(){ 44 | this.directoryInput.text = this.exportSettings.directory; 45 | } 46 | }; 47 | pack.SettingsPanel = SettingsPanel; 48 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/StringControl.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function StringControl(container, value, optional){ 3 | this.init(container, value, optional); 4 | return this; 5 | } 6 | 7 | 8 | 9 | StringControl.prototype={ 10 | onChange:null, 11 | 12 | init:function(container, value, optional){ 13 | var scopedThis = this; 14 | 15 | if(value==null)value = ""; 16 | 17 | this.value = value; 18 | this.optional = optional; 19 | 20 | var row = container.add("group"); 21 | row.orientation = "row"; 22 | row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.CENTER]; 23 | 24 | var inputW; 25 | if(optional){ 26 | this.checkbox = row.add('checkbox'); 27 | this.checkbox.value = (value!=null && value!=""); 28 | this.checkbox.size = [16, 16]; 29 | this.checkbox.onClick = function(){ 30 | scopedThis.input.enabled = scopedThis.checkbox.value; 31 | } 32 | inputW = 175; 33 | }else{ 34 | inputW = 200; 35 | } 36 | 37 | this.input = row.add('edittext', undefined, value); 38 | this.input.preferredSize = [inputW, 20]; 39 | this.input.onChange = function(){ 40 | scopedThis.setValue(scopedThis.input.text); 41 | } 42 | if(optional){ 43 | this.input.enabled = this.checkbox.value; 44 | } 45 | }, 46 | setValue : function(value){ 47 | this.value = value; 48 | this.input.text = value; 49 | if(this.optional){ 50 | this.checkbox.value = (value!=""); 51 | this.input.enabled = this.checkbox.value; 52 | } 53 | if(onChange)onChange(); 54 | }, 55 | 56 | getValue : function(){ 57 | return !this.optional || this.checkbox.value?this.value:null; 58 | } 59 | }; 60 | pack.StringControl = StringControl; 61 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/ExportDialog.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function ExportDialog(presetDir, settingsExt){ 3 | this.presetDir = presetDir; 4 | this.settingsExt = settingsExt; 5 | this.init(); 6 | return this; 7 | } 8 | ExportDialog.prototype={ 9 | 10 | controls:null, 11 | 12 | init:function(){ 13 | var scopedThis = this; 14 | 15 | this.dialog = new Window('dialog', "Export which settings?"); 16 | this.dialog.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 17 | 18 | this.presetList = this.dialog.add ('ListBox', [0, 0, 200, 200], '', 19 | {numberOfColumns: 1, showHeaders: false, multiselect:false, 20 | columnTitles: ['Format'] }); 21 | 22 | this.presetList.add("item", "--- Current Settings ---"); 23 | var allFiles = this.presetDir.getFiles(); 24 | this.files = []; 25 | for(var i=0; i 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ./panel.html 34 | 35 | 36 | false 37 | 38 | 39 | 40 | ModalDialog 41 | {AppTitle} 42 | 43 | 44 | 200 45 | 200 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | ./previous.html 57 | 58 | 59 | false 60 | 61 | 62 | 63 | ModalDialog 64 | {AppTitle}: Run Again 65 | 66 | 67 | 200 68 | 200 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /SmartCore/ExportPanel.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function ExportPanel(container, exportSettings){ 3 | this.init(container, exportSettings); 4 | return this; 5 | } 6 | 7 | ExportPanel.prototype={ 8 | onCancelClicked:null, 9 | onSaveCloseClicked:null, 10 | onExportClicked:null, 11 | onIgnoreWarningsChanged:null, 12 | 13 | init:function(container, exportSettings){ 14 | var scopedThis = this; 15 | this.exportSettings = exportSettings; 16 | 17 | // main row 18 | var mainRow = container.add('group', undefined, ''); 19 | mainRow.size = [650, 30]; 20 | mainRow.alignment = [ScriptUI.Alignment.RIGHT, ScriptUI.Alignment.TOP]; 21 | mainRow.orientation = 'row' 22 | 23 | 24 | // options row 25 | var optionRow = mainRow.add('group', undefined, ''); 26 | optionRow.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 27 | optionRow.orientation = 'row' 28 | 29 | 30 | this.ignoreCheckBox = optionRow.add('checkbox', undefined, 'Ignore Warnings'); 31 | this.ignoreCheckBox.value = exportSettings.ignoreWarnings; 32 | this.ignoreCheckBox.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.BOTTOM]; 33 | this.ignoreCheckBox.onClick = function() { 34 | scopedThis.exportSettings.ignoreWarnings = scopedThis.ignoreCheckBox.value; 35 | if(scopedThis.onIgnoreWarningsChanged)scopedThis.onIgnoreWarningsChanged(); 36 | }; 37 | 38 | 39 | // buttons row 40 | var buttonRow = mainRow.add('group', undefined, ''); 41 | buttonRow.alignment = [ScriptUI.Alignment.RIGHT, ScriptUI.Alignment.TOP]; 42 | buttonRow.orientation = 'row' 43 | 44 | var cancelBtn = buttonRow.add('button', undefined, 'Cancel', {name:'cancel'}); 45 | cancelBtn.preferredSize = [80, 22]; 46 | cancelBtn.onClick = function() { 47 | if(scopedThis.onCancelClicked)scopedThis.onCancelClicked(); 48 | }; 49 | 50 | // Save button 51 | var saveBtn = buttonRow.add('button', undefined, 'Done', {name:'save'}); 52 | saveBtn.preferredSize = [100, 22]; 53 | saveBtn.onClick = function() { 54 | if(scopedThis.onSaveCloseClicked)scopedThis.onSaveCloseClicked(); 55 | }; 56 | 57 | // OK button 58 | var exportBtn = buttonRow.add('button', undefined, 'Export', {name:'ok'}); 59 | exportBtn.preferredSize = [100, 22]; 60 | exportBtn.onClick = function() { 61 | if(scopedThis.onExportClicked)scopedThis.onExportClicked(); 62 | }; 63 | }, 64 | updateSettings:function(){ 65 | this.ignoreCheckBox.value = this.exportSettings.ignoreWarnings; 66 | } 67 | }; 68 | pack.ExportPanel = ExportPanel; 69 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/SaveSettingsDialog.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function SaveSettingsDialog(){ 3 | this.init(); 4 | return this; 5 | } 6 | SaveSettingsDialog.prototype={ 7 | 8 | controls:null, 9 | 10 | init:function(){ 11 | var scopedThis = this; 12 | 13 | this.dialog = new Window('dialog', "Add New Preset"); 14 | this.dialog.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 15 | 16 | var nameRow = this.dialog.add("group"); 17 | nameRow.orientation = "row"; 18 | nameRow.alignment = [ScriptUI.Alignment.CENTER, ScriptUI.Alignment.TOP]; 19 | 20 | nameRow.add("statictext", undefined, "Preset name:"); 21 | 22 | this.input = nameRow.add("edittext", undefined, ""); 23 | this.input.preferredSize = [190, 22]; 24 | 25 | this.generalCheckbox = this.dialog.add("checkbox", undefined, "Save Destination Folder"); 26 | this.generalCheckbox.value = true; 27 | this.generalCheckbox.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 28 | 29 | this.formatCheckbox = this.dialog.add("checkbox", undefined, "Save Format Settings"); 30 | this.formatCheckbox.value = true; 31 | this.formatCheckbox.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 32 | this.formatCheckbox.onClick = function(){ 33 | scopedThis.patternCheckbox.enabled = scopedThis.formatCheckbox.value; 34 | } 35 | 36 | this.patternCheckbox = this.dialog.add("checkbox", undefined, "Save Filename Patterns"); 37 | this.patternCheckbox.value = true; 38 | this.patternCheckbox.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 39 | 40 | var buttonRow = this.dialog.add("group"); 41 | buttonRow.orientation = "row"; 42 | buttonRow.alignment = [ScriptUI.Alignment.CENTER, ScriptUI.Alignment.TOP]; 43 | 44 | this.cancelButton = buttonRow.add('button', undefined, 'Cancel', {name:'cancel'}); 45 | this.cancelButton.onClick = function() { 46 | scopedThis.dialog.close(); 47 | }; 48 | 49 | this.saveButton = buttonRow.add('button', undefined, 'Save', {name:'ok'}); 50 | this.saveButton.onClick = function() { 51 | if(!scopedThis.input.text){ 52 | alert("Please choose a name for these settings"); 53 | return; 54 | } 55 | scopedThis.text = scopedThis.input.text; 56 | scopedThis.patterns = scopedThis.patternCheckbox.value; 57 | scopedThis.generalSettings = scopedThis.generalCheckbox.value; 58 | scopedThis.formatSettings = scopedThis.formatCheckbox.value; 59 | scopedThis.dialog.close(); 60 | }; 61 | 62 | this.dialog.show(); 63 | } 64 | }; 65 | pack.SaveSettingsDialog = SaveSettingsDialog; 66 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/FilePatternControl.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function FilePatternControl(container, label, value, tokens){ 3 | this.init(container, label, value, tokens); 4 | return this; 5 | } 6 | 7 | 8 | 9 | FilePatternControl.prototype={ 10 | onChange:null, 11 | 12 | init:function(container, label, value, tokens){ 13 | var scopedThis = this; 14 | 15 | if(value==null)value = ""; 16 | 17 | this.value = value; 18 | this.tokens = tokens; 19 | 20 | // if(container.orientation == "column"){ 21 | // var column = container; 22 | // }else{ 23 | // var column = container.add('group'); 24 | // column.orientation = "column"; 25 | // row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 26 | // } 27 | var column = container; 28 | 29 | var row = column.add('group', undefined, '') 30 | row.orientation = 'row'; 31 | row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 32 | 33 | this.label = row.add('statictext', undefined, label); 34 | this.label.size = [60,20]; 35 | 36 | this.input = row.add('edittext', undefined, value); 37 | this.input.size = [ 360,20 ]; 38 | 39 | this.dropdown = new pack.Dropdown(row, tokens); 40 | //this.dropdown = row.add('dropdownlist', undefined, tokens); 41 | this.dropdown.onChange = function() { 42 | scopedThis.addToken(); 43 | }; 44 | this.dropdown.setSize(110,20); 45 | this.dropdown.setSelection(0); 46 | 47 | // row = column.add('group', undefined, '') 48 | // row.orientation = 'row'; 49 | // row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 50 | 51 | // this.input = row.add('edittext', undefined, value); 52 | // this.input.size = [ 340,20 ]; 53 | 54 | this.input.onChange = function() { 55 | scopedThis.setValue(scopedThis.input.text); 56 | }; 57 | this.input.addEventListener("keyup", this.input.onChange); 58 | }, 59 | setValue : function(value){ 60 | this.value = value; 61 | this.input.text = value; 62 | if(this.onChange)this.onChange(); 63 | }, 64 | 65 | getValue : function(){ 66 | return this.value; 67 | }, 68 | 69 | addToken:function(){ 70 | if(this.dropdown.selection>0){ 71 | var selected = Number(this.dropdown.selection); 72 | var token = this.tokens[selected]; 73 | this.setValue(this.input.text + token); 74 | this.dropdown.setSelection(0); 75 | } 76 | }, 77 | setEnabled : function(value){ 78 | this.label.enabled = value; 79 | this.input.enabled = value; 80 | this.dropdown.setEnabled(value); 81 | } 82 | }; 83 | pack.FilePatternControl = FilePatternControl; 84 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/PreviewFilesPanel.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function PreviewFilesPanel(container){ 3 | this.init(container); 4 | return this; 5 | } 6 | 7 | PreviewFilesPanel.prototype={ 8 | onPatternChanged:null, 9 | shown:false, 10 | invalid:false, 11 | 12 | init:function(container){ 13 | 14 | this.list = container.add ('ListBox', [0, 0, 630, 470], 'asd', 15 | {numberOfColumns: 4, showHeaders: true, 16 | columnTitles: ['', '', '', 'Filename'] }); 17 | }, 18 | updateList:function(bundleList){ 19 | this.bundleList = bundleList; 20 | this.refreshList(); 21 | }, 22 | refreshList:function(){ 23 | if(!this.shown){ 24 | this.invalid = true; 25 | return; 26 | } 27 | 28 | var lastArtboard; 29 | this.list.removeAll(); 30 | var docRef = app.activeDocument; 31 | var lastNames = []; 32 | this.flattenedList = []; 33 | for(var i=0; i this.timeAllowance){ 62 | this.timeDefecit -= this.timeAllowance; 63 | pack.Timer.addFrameHandler(this, this.doFrame); 64 | return; 65 | } 66 | //fl.trace("--------------FRAME------------ "); 67 | var maxTime = getTimer() + this.timeAllowance - this.timeDefecit; 68 | while(getTimer() < maxTime && this.queue.length){ 69 | var curr = this.queue[0]; 70 | this.label = curr.label + (curr.subLabel?" - "+curr.subLabel:""); 71 | curr.handler(); 72 | if(curr != this.queue[0]){ 73 | this.label = ""; 74 | // was removed 75 | if(curr.run < curr.count)this.progress += curr.count-curr.run; 76 | }else{ 77 | curr.run++; 78 | if(curr.run <= curr.count){ 79 | this.progress++; 80 | if(curr.autoRemove && curr.run == curr.count){ 81 | this.removeCurrent(); 82 | } 83 | } 84 | } 85 | } 86 | this.timeDefecit = getTimer() - maxTime; 87 | if(this.queue.length){ 88 | pack.Timer.addFrameHandler(this, this.doFrame); 89 | }else{ 90 | this.label = ""; 91 | this.progress = 0; 92 | this.total = 0; 93 | } 94 | this.updateProgress(); 95 | }, 96 | updateProgress:function(){ 97 | if(this.progressHandler)this.progressHandler(this.progress, this.total); 98 | } 99 | }; 100 | pack.Queue = Queue; 101 | })(smartExport) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adobe Illustrator Smart Export 2 | 3 | ### (aka SmartLayerExport) 4 | 5 | This plugin is used to export Artboards/Layers/Symbols/Elements, these sources can be exported to multiple different formats (e.g. PNG, PDF, JPG, AI, etc). 6 | 7 | Once you have set up export settings for a document, these settings can be saved in the document so that you don't need to redo them. 8 | 9 | Export settings can also be saved as presets, which can be imported/exported for sharing. 10 | 11 | ***This plugin is no longer actively being maintained, please see below for contributing to the project.*** 12 | 13 | ### Features: 14 | 15 | - Ability to scale output files for HiDPI (Retina) displays, or any other scale factor. 16 | - Can set up multiple export formats for a single file for easy regeneration of multiple asset sizes/types. 17 | - Settings are saved within Illustrator file so that settings are remembered next time you open the panel. 18 | - Layers can be trimmed down to the size of the layer itself or exported at the artboard's size. 19 | - File name pattern allows for full flexibility of output file names. 20 | - Can optionally export full Artboard images as well as individual layer images. 21 | - Can Load/Save/Import/Export settings. 22 | - Has a feature to 'Run Again' (CC only) 23 | 24 | ### Current Formats: 25 | 26 | - PNG 8 27 | - PNG 24 28 | - PDF 29 | - JPG 30 | - GIF 31 | - EPS 32 | - SVG 33 | - SVGZ 34 | - TIFF 35 | - AI 36 | - FXG (CS6 Only) 37 | 38 | ## Installation 39 | 40 | - Select latest release from [releases page](https://github.com/TomByrne/IllustratorSmartExport/releases) 41 | - Install with one of the following tools: 42 | - [ZXPInstaller](http://zxpinstaller.com/) (recommended) 43 | - Extension Manager (installed with Adobe applications) 44 | - [ExManCmd](https://www.adobeexchange.com/resources/28) 45 | 46 | ## Usage 47 | 48 | **For CS version:** Goto File > Scripts > Smart Layer Export 49 | 50 | **For CC version:** Goto Window > Extensions > Smart Export 51 | 52 | ## Build process 53 | 54 | At the moment, the build process is run locally, and it only works on Windows. 55 | 56 | This is done by double-clicking `build/BuildAll.bat`. 57 | 58 | There is the intention to migrate this to Travis CI at some point (but no resources). 59 | 60 | The build process currently spits out different versions of the plugin installer based on the `Version_*` folders, to support multiple vendors with different settings (e.g. plugin name, plugin ID, features available). Also this will likely be removed if the build process is reworked. 61 | 62 | The build process also generates two installers per `Version_*` folder, one for Illustrator CC, and one for Illustrator CS. The CC version gets installed in a slightly different way, which allows for multiple entry points. 63 | 64 | ## Contributing 65 | 66 | To contribute to the plugin, please create an issue in the Github issue tracker above, so that it's clear what needs to be resolved/improved. 67 | 68 | After making your changes in your own fork of the repo, create a Pull Request back into this repo named after the issue it intends to solve. 69 | 70 | If the changes are accepted a new build/release will be created on the Releases page. -------------------------------------------------------------------------------- /SmartCore/SymbolPanel.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function SymbolPanel(container, selectAll, selectedNames){ 3 | this.init(container, selectAll, selectedNames); 4 | return this; 5 | } 6 | 7 | SymbolPanel.prototype={ 8 | onSelectedChanged:null, 9 | 10 | init:function(container, selectAll, selectedNames){ 11 | this.selectAll = selectAll; 12 | this.selectedNames = selectedNames; 13 | 14 | var scopedThis = this; 15 | var column = container.add('group', undefined, '') 16 | column.orientation = 'column'; 17 | column.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 18 | 19 | this.listbox = column.add ('ListBox', [0, 0, 630, 450], '', 20 | {numberOfColumns: 3, showHeaders: false, multiselect:true, 21 | columnTitles: ['', '', 'Symbol'] }); 22 | this.listbox.onChange = function(){ 23 | scopedThis.checkSelection(); 24 | } 25 | 26 | var docRef = app.activeDocument; 27 | for(var i=0; i totalItems-1) selectedInd = totalItems-1; 31 | this.tabPanel.selection = selectedInd; 32 | }, 33 | add:function(label){ 34 | this.items.push(label); 35 | return this.tabPanel.add("tab", undefined, label); 36 | } 37 | }; 38 | 39 | }else{ 40 | 41 | 42 | function indexOf ( array, element ) { 43 | for(var i=0; i 2 | 4 3 | 4 | 5 | true 6 | 7 | 8 | 9 | 10 | PNG 24 11 | 100 12 | artboard 13 | false 14 | AndroidIcons 15 | high 16 | true 17 | 18 | <ArtboardName>_<LayerName>/launcher_store_512.<Ext> 19 | <ArtboardName>/launcher_store_512.<Ext> 20 | <SymbolName>/launcher_store_512.<Ext> 21 | <ArtboardName>_ElementName>/launcher_store_512.<Ext> 22 | 23 | 24 | 25 | 26 | 27 | PNG 24 28 | 37.5 29 | artboard 30 | false 31 | AndroidIcons 32 | high 33 | true 34 | 35 | <ArtboardName>_<LayerName>/launcher_xxxhdpi_192.<Ext> 36 | <ArtboardName>/launcher_xxxhdpi_192.<Ext> 37 | <SymbolName>/launcher_xxxhdpi_192.<Ext> 38 | <ArtboardName>_<ElementName>/launcher_xxxhdpi_192.<Ext> 39 | 40 | 41 | 42 | 43 | 44 | PNG 24 45 | 28.125 46 | artboard 47 | false 48 | AndroidIcons 49 | high 50 | true 51 | 52 | <ArtboardName>_<LayerName>/launcher_xxhdpi_144.<Ext> 53 | <ArtboardName>/launcher_xxhdpi_144.<Ext> 54 | <SymbolName>/launcher_xxhdpi_144.<Ext> 55 | <ArtboardName>_ElementName>/launcher_xxhdpi_144.<Ext> 56 | 57 | 58 | 59 | 60 | 61 | PNG 24 62 | 18.75 63 | artboard 64 | false 65 | AndroidIcons 66 | high 67 | true 68 | 69 | <ArtboardName>_<LayerName>/launcher_xhdpi_96.<Ext> 70 | <ArtboardName>/launcher_xhdpi_96.<Ext> 71 | <SymbolName>/launcher_xhdpi_96.<Ext> 72 | <ArtboardName>_<ElementName>/launcher_xhdpi_96.<Ext> 73 | 74 | 75 | 76 | 77 | 78 | PNG 24 79 | 14.0625 80 | artboard 81 | false 82 | AndroidIcons 83 | high 84 | true 85 | 86 | <ArtboardName>_<LayerName>/launcher_hdpi_72.<Ext> 87 | <ArtboardName>/launcher_hdpi_72.<Ext> 88 | <SymbolName>/launcher_hdpi_72.<Ext> 89 | <ArtboardName>_<ElementName>/launcher_hdpi_72.<Ext> 90 | 91 | 92 | 93 | 94 | 95 | PNG 24 96 | 9.375 97 | artboard 98 | false 99 | AndroidIcons 100 | high 101 | true 102 | 103 | <ArtboardName>_<LayerName>/launcher_mdpi_48.<Ext> 104 | <ArtboardName>/launcher_mdpi_48.<Ext> 105 | <SymbolName>/launcher_mdpi_48.<Ext> 106 | <ArtboardName>_<ElementName>/launcher_mdpi_48.<Ext> 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /SmartCore/ColorPicker.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function ColorPicker(container, color, optional){ 3 | this.init(container, color, optional); 4 | return this; 5 | } 6 | 7 | 8 | function pad(str, count, pad){ 9 | while(str.length < count){ 10 | str = pad + str; 11 | } 12 | return str; 13 | } 14 | 15 | function parseColor(colStr){ 16 | colStr = colStr.split("#").join(""); 17 | if(colStr.length>6)colStr = colStr.substr(colStr.length - 6, colStr.length); 18 | return parseInt(colStr, 16); 19 | } 20 | function formatColor(col){ 21 | if(col==null)col = 0; 22 | return "#" + pad(col.toString(16), 6, "0"); 23 | } 24 | function colorToRGB(col){ 25 | if(col==null)col = 0; 26 | var ret = []; 27 | ret[0] = ((col >> 16) & 0xff) / 0xff; 28 | ret[1] = ((col >> 8) & 0xff) / 0xff; 29 | ret[2] = (col & 0xff) / 0xff; 30 | return ret; 31 | } 32 | function rgbToColor(rgb){ 33 | return Math.round(rgb[0] * 0xff)<<16 | Math.round(rgb[1] * 0xff)<<8 | Math.round(rgb[2] * 0xff); 34 | } 35 | 36 | 37 | /* 38 | The line width, in pixels, for the main color swatch. 39 | @type Number 40 | */ 41 | var kSwatchBorderWidth = 1; 42 | 43 | function drawRGBSwatch (drawingStateObj) 44 | { 45 | var gfx = this.graphics; 46 | gfx.strokePath (this.fillPen, this.boxPath); 47 | gfx.strokePath (this.shadowPen, this.boxPath); 48 | } 49 | function updateSwatch (swatchGrp, swatchBtn, rgbValue) 50 | { 51 | var swatchGfx = swatchGrp.graphics; 52 | swatchGfx.backgroundColor = swatchGfx.newBrush (swatchGfx.BrushType.SOLID_COLOR, rgbValue); 53 | swatchGfx.disabledBackgroundColor = swatchGfx.backgroundColor; 54 | swatchBtn.fillPen = swatchGfx.newPen (swatchGfx.PenType.SOLID_COLOR, rgbValue, kSwatchBorderWidth); 55 | } 56 | 57 | ColorPicker.prototype={ 58 | onChange:null, 59 | 60 | init:function(container, color, optional){ 61 | var scopedThis = this; 62 | 63 | this.optional = optional; 64 | 65 | if(typeof(color)=="string")color = parseColor(color); 66 | 67 | var row = container.add("group"); 68 | row.orientation = "row"; 69 | row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.CENTER]; 70 | 71 | if(optional){ 72 | this.checkbox = row.add('checkbox'); 73 | this.checkbox.value = (color!=null); 74 | this.checkbox.size = [16, 16]; 75 | /*this.checkbox.onClick = function(){ 76 | scopedThis.input.enabled = scopedThis.checkbox.value; 77 | scopedThis.button.enabled = scopedThis.checkbox.value; 78 | }*/ 79 | } 80 | 81 | this.input = row.add('edittext', undefined, formatColor(color)); 82 | this.input.preferredSize = [65, 20]; 83 | 84 | this.group = row.add("group"); 85 | this.group.size = [16, 16]; 86 | 87 | this.button = this.group.add("button"); 88 | this.button.size = [16, 16]; 89 | this.button.onDraw = drawRGBSwatch; 90 | 91 | this.button.onClick = function(){ 92 | var color = $.colorPicker(); 93 | if(color!=-1){ 94 | scopedThis.checkbox.value = true; 95 | scopedThis.setColor(color); 96 | } 97 | } 98 | this.input.onChange = function(){ 99 | scopedThis.setColorStr(scopedThis.input.text); 100 | scopedThis.checkbox.value = true; 101 | } 102 | var gfx = this.button.graphics; 103 | var btnW = this.button.size.width; 104 | var btnH = this.button.size.height; 105 | // Define the top-left and bottom-right border paths 106 | var halfBorderW = kSwatchBorderWidth / 2; 107 | gfx.newPath(); 108 | gfx.moveTo (halfBorderW, btnH - halfBorderW); 109 | gfx.lineTo (halfBorderW, halfBorderW); 110 | gfx.lineTo (btnW - halfBorderW, halfBorderW); 111 | gfx.lineTo (btnW - halfBorderW, btnH - halfBorderW); 112 | gfx.lineTo (halfBorderW, btnH - halfBorderW); 113 | this.button.boxPath = gfx.currentPath; 114 | 115 | this.button.shadowPen = gfx.newPen (gfx.PenType.SOLID_COLOR, [0, 0, 0, 1], kSwatchBorderWidth); 116 | 117 | /*if(optional && !this.checkbox.value){ 118 | this.input.enabled = false; 119 | this.button.enabled = false; 120 | }*/ 121 | 122 | this.rgbValue = colorToRGB(color); 123 | updateSwatch(this.group, this.button, this.rgbValue); 124 | }, 125 | 126 | setColorStr : function(colStr){ 127 | var color = parseColor(colStr); 128 | this.input.text = formatColor(color); 129 | this.rgbValue = colorToRGB(color); 130 | updateSwatch(this.group, this.button, this.rgbValue); 131 | if(this.onChange)this.onChange(); 132 | }, 133 | 134 | getColorStr : function(){ 135 | return !this.optional || this.checkbox.value?formatColor(rgbToColor(this.rgbValue)):null; 136 | }, 137 | 138 | setColor : function(color){ 139 | this.input.text = formatColor(color); 140 | this.rgbValue = colorToRGB(color); 141 | updateSwatch(this.group, this.button, this.rgbValue); 142 | if(this.onChange)this.onChange(); 143 | }, 144 | 145 | getColor : function(){ 146 | return !this.optional || this.checkbox.value?rgbToColor(this.rgbValue):null; 147 | } 148 | }; 149 | pack.ColorPicker = ColorPicker; 150 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/LayerPanel.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function LayerPanel(container, selectAll, selectedIndices, ignoreLayerNames, ignoreOutOfBounds){ 3 | this.init(container, selectAll, selectedIndices, ignoreLayerNames, ignoreOutOfBounds); 4 | return this; 5 | } 6 | 7 | LayerPanel.prototype={ 8 | onSelectedChanged:null, 9 | onIgnoreOutOfBoundsChanged:null, 10 | 11 | init:function(container, selectAll, selectedIndices, ignoreLayerNames, ignoreOutOfBounds){ 12 | this.selectAll = selectAll; 13 | this.selectedIndices = selectedIndices; 14 | this.ignoreOutOfBounds = ignoreOutOfBounds; 15 | 16 | var scopedThis = this; 17 | var column = container.add('group', undefined, '') 18 | column.orientation = 'column'; 19 | column.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 20 | 21 | this.layerList = column.add ('ListBox', [0, 0, 420, 450], '', 22 | {numberOfColumns: 3, showHeaders: false, multiselect:true, 23 | columnTitles: ['', '', 'Layer'] }); 24 | this.layerList.onChange = function(){ 25 | scopedThis.checkSelection(); 26 | } 27 | 28 | var docRef = app.activeDocument; 29 | var j = 0; 30 | for(var i=0; i'); 41 | ret.appendChild( new XML(''+this.format+'') ); 42 | if(this.hasProp("scaling") && this.scaling)ret.appendChild( new XML(''+this.scaling+'') ); 43 | if(this.hasProp("ungroup"))ret.appendChild( new XML(''+this.ungroup+'') ); 44 | if(this.hasProp("embedImage"))ret.appendChild( new XML(''+this.embedImage+'') ); 45 | if(this.hasProp("boundsMode"))ret.appendChild( new XML(''+this.boundsMode+'') ); 46 | if(this.hasProp("innerPadding"))ret.appendChild( new XML(''+this.innerPadding+'') ); 47 | if(this.directory) ret.appendChild( new XML(''+this.directory+'') ); 48 | if(this.fontHandling && this.fontHandling!="none") ret.appendChild( new XML(''+this.fontHandling+'') ); 49 | if(this.colorSpace && this.colorSpace!="none") ret.appendChild( new XML(''+this.colorSpace+'') ); 50 | if(this.rasterResolution && this.rasterResolution!="none") ret.appendChild( new XML(''+this.rasterResolution+'') ); 51 | if(this.preset) ret.appendChild( new XML(''+this.preset+'') ); 52 | if(this.active != null) ret.appendChild( new XML(''+this.active+'') ); 53 | 54 | if(includePatterns){ 55 | var patterns = new XML(''); 56 | for(var i in this.patterns){ 57 | patterns.appendChild( new XML('<'+i+'>'+this.xmlEncode(this.patterns[i])+'') ); 58 | } 59 | ret.appendChild(patterns); 60 | } 61 | 62 | var options = new XML(''); 63 | for(var i in this.options){ 64 | options.appendChild( new XML('<'+i+'>'+this.options[i]+'') ); 65 | } 66 | ret.appendChild(options); 67 | return ret; 68 | }, 69 | xmlEncode:function(str){ 70 | str = str.split("&").join("&"); 71 | str = str.split("<").join("<"); 72 | str = str.split(">").join(">"); 73 | str = str.split('"').join("""); 74 | str = str.split("'").join("'"); 75 | return str; 76 | }, 77 | 78 | parseObjectNode:function(parentNode){ 79 | var children = parentNode.children(); 80 | var ret = {}; 81 | for(var i=0; i 0 && (doc.layers.length!=1 || doc.layers[0].pageItems.length || doc.layers[0].layers.length); 95 | 96 | var artb = doc.artboards[0]; 97 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM; 98 | var new_layer = pack.DocUtils.copyLayer(docRef, doc, artb, doc.artboards[0], artb.artboardRect, layer, doc.layers.add(), padding, doOutline, ungroup, docRef.rulerOrigin, exportSettings.ignoreWarnings, SymbolBundler.hasBoundErrorRef); 99 | return doc; 100 | } 101 | 102 | 103 | return null; 104 | } 105 | SymbolBundler.cleanupCopyDoc = function(docRef, exportSettings, exportBundle){ 106 | //exportBundle.copyDoc.close(SaveOptions.DONOTSAVECHANGES); 107 | pack.DocCloser.closeDocument(exportBundle.copyDoc); 108 | exportBundle.copyDoc = null; 109 | SymbolBundler.testLayer.symbolItems.removeAll(); 110 | } 111 | SymbolBundler.cleanupTempLayer = function(docRef, exportSettings, exportBundle){ 112 | SymbolBundler.cleanupCopyDoc(docRef, exportSettings, exportBundle); 113 | SymbolBundler.testLayer.remove(); 114 | SymbolBundler.testLayer = null; 115 | } 116 | 117 | SymbolBundler.makeFileName = function(pattern, ext, symbolName){ 118 | var ret = pattern.split(pack.tokens.SYMBOL_NAME_TOKEN).join(symbolName); 119 | ret = ret.split(pack.tokens.FILE_EXT_TOKEN).join(ext); 120 | return ret; 121 | } 122 | SymbolBundler.indexOf = function ( array, element ) { 123 | for(var i=0; i= docRef.artboards.length) continue; 15 | 16 | var artboard = docRef.artboards[artI]; 17 | var artboardName = artboard.name; 18 | 19 | var bundleMap = {}; 20 | 21 | for (var x = 0; x < exportSettings.formats.length; x++ ) { 22 | var formatSettings = exportSettings.formats[x]; 23 | var filePattern = formatSettings.patterns[patternName]; 24 | if(!formatSettings.active || filePattern == '' || filePattern == null) continue; 25 | 26 | var format = formatSettings.formatRef; 27 | var bundle = this.getBundle(bundleMap, artI, formatSettings.innerPadding, formatSettings.scaling, formatSettings.boundsMode, format.copyBehaviour, formatSettings.fontHandling=="outline", formatSettings.ungroup, formatSettings.colorSpace, formatSettings.rasterResolution); 28 | 29 | var item = new pack.ExportItem(formatSettings, ArtboardBundler.makeFileName(filePattern, docRef.fullName.name, formatSettings.formatRef.ext, i, artboardName)); 30 | item.names = ["Artboard "+(artI+1)]; 31 | bundle.items.push(item); 32 | 33 | hasExports = true; 34 | } 35 | 36 | for(var j in bundleMap){ 37 | bundle = bundleMap[j]; 38 | if(bundle.items.length){ 39 | bundles.push(bundle); 40 | } 41 | } 42 | } 43 | 44 | return hasExports; 45 | } 46 | ArtboardBundler.getBundle = function(bundleMap, artI, padding, scaling, boundsMode, forceCopy, doOutline, ungroup, colorSpace, rasterResolution){ 47 | var trim = boundsMode!=pack.BoundsMode.ARTBOARD; 48 | if(doOutline || padding || trim || colorSpace) forceCopy = true; 49 | 50 | var key = (padding?"pad":"nopad")+"_"+(forceCopy?"copy":"nocopy")+"_"+(doOutline?"outline":"nooutline")+"_"+boundsMode + "_" + (colorSpace==null ? "" : "_"+colorSpace) + (rasterResolution==null ? "" : "_"+rasterResolution); 51 | var bundle = bundleMap[key]; 52 | if(bundle){ 53 | return bundle; 54 | }else if(!forceCopy){ 55 | // export types which don't require a new document to be created just show/hide layers to complete export. (No pad, raster exports) 56 | bundle = new pack.ExportBundle(); 57 | bundle.prepareHandler = closure(ArtboardBundler, ArtboardBundler.prepareRegular, [artI], true); 58 | 59 | }else{ 60 | bundle = new pack.ExportBundle(); 61 | bundle.prepareHandler = closure(ArtboardBundler, ArtboardBundler.prepareCopy, [artI, boundsMode, padding, doOutline, ungroup, colorSpace, rasterResolution], true); 62 | bundle.cleanupHandler = ArtboardBundler.cleanupCopy; 63 | 64 | } 65 | bundleMap[key] = bundle; 66 | return bundle; 67 | } 68 | ArtboardBundler.prepareRegular = function(docRef, exportSettings, exportBundle, artI){ 69 | docRef.artboards.setActiveArtboardIndex(artI); 70 | return docRef; 71 | } 72 | ArtboardBundler.prepareCopy = function(docRef, exportSettings, exportBundle, artI, boundsMode, padding, doOutline, ungroup, colorSpace, rasterResolution){ 73 | var artboard = docRef.artboards[artI]; 74 | docRef.artboards.setActiveArtboardIndex(artI); 75 | 76 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM; 77 | var rect = artboard.artboardRect; 78 | 79 | var layerCheck = function(layer){ 80 | return (layer.visible && DocUtils.indexOf(pack.IGNORE_LAYERS, layer.name)==-1); 81 | }; 82 | 83 | var offset; 84 | if(boundsMode!=pack.BoundsMode.ARTBOARD){ 85 | var allLayerBounds; 86 | for(var i=0; ilayerBounds[0]){ 97 | allLayerBounds[0] = layerBounds[0]; 98 | } 99 | if(allLayerBounds[1]layerBounds[3]){ 106 | allLayerBounds[3] = layerBounds[3]; 107 | } 108 | } 109 | } 110 | if(!allLayerBounds)return "skipped"; 111 | 112 | // crop to artboard 113 | if(boundsMode==pack.BoundsMode.ARTBOARD_AND_ARTWORK){ 114 | if(allLayerBounds[0]rect[1]){ 118 | allLayerBounds[1] = rect[1]; 119 | } 120 | if(allLayerBounds[2]>rect[2]){ 121 | allLayerBounds[2] = rect[2]; 122 | } 123 | if(allLayerBounds[3]1){ 135 | var dirObj = Folder(path); 136 | if(!dirObj.exists){ 137 | dirObj.create(); 138 | } 139 | } 140 | } 141 | 142 | if(Folder.fs=="Windows"){ 143 | fileName = fileName.split('/').join('\\'); 144 | } 145 | 146 | // Center the view 147 | var bounds; 148 | if(copyDoc.artboards.length == 1){ 149 | bounds = copyDoc.artboards[0].artboardRect; 150 | }else{ 151 | bounds = copyDoc.geometricBounds; 152 | } 153 | var centerX = (bounds[0] + bounds[2]) / 2; 154 | var centerY = (bounds[1] + bounds[3]) / 2; 155 | copyDoc.activeView.centerPoint = [centerX, centerY]; 156 | 157 | formatSettings.formatRef.saveFile(copyDoc, fileName, item.formatSettings.saveOptions ); 158 | if(File(fileName).exists){ 159 | item.state = "success"; 160 | }else{ 161 | failed.push(item); 162 | item.state = "failed"; 163 | } 164 | 165 | }catch(e){ 166 | alert("Save Failed: "+e); 167 | failed.push(item); 168 | item.state = "failed"; 169 | } 170 | } 171 | this.updateProgress(++this.num_exported, this.num_to_export); 172 | this.updatedExportItem(item); 173 | //$.sleep(40) // Allows UI update; 174 | } 175 | 176 | if(copyDoc/* && copyDoc!="skipped" && copyDoc!="failed"*/){ 177 | if(bundle.cleanupHandler)bundle.cleanupHandler(docRef, this.exportSettings, bundle); 178 | } 179 | }catch(e){ 180 | alert(e); 181 | try{ 182 | if(bundle.cleanupHandler)bundle.cleanupHandler(docRef, this.exportSettings, bundle); 183 | }catch(e){} 184 | 185 | for(i; i n) msg += "\nPlus "+(failed.length - n)+" more"; 203 | msg += "\n\nTry again?"; 204 | if(confirm(msg)){ 205 | return this.doRun(); 206 | }else{ 207 | return this.doFinish(false, failed); 208 | } 209 | }else{ 210 | return this.doFinish(true, failed); 211 | } 212 | }, 213 | 214 | doFinish: function(success, failed){ 215 | this.running = false; 216 | if(this.onExportFinished){ 217 | if(success){ 218 | this.onExportFinished(true, null); 219 | }else{ 220 | this.onExportFinished(null, true); 221 | } 222 | } 223 | var successCount = this.num_exported - failed.length; 224 | // This alert prevents crashing 225 | if(success){ 226 | alert(successCount + " exports were successful"); 227 | 228 | }else if(successCount){ 229 | alert(successCount + " exports were successful.\n" + failed.length + " exports failed."); 230 | 231 | }else{ 232 | alert("All " + failed.length + "exports failed."); 233 | } 234 | 235 | pack.DocCloser.closePending(); 236 | return success; 237 | }, 238 | 239 | cancel:function(){ 240 | this.cancelled = true; 241 | }, 242 | 243 | indexOf: function ( array, element ) { 244 | for(var i=0; i6)colStr = colStr.substr(colStr.length - 6, colStr.length); 18 | return parseInt(colStr, 16); 19 | } 20 | function formatColor(col){ 21 | if(col==null)col = 0; 22 | return "#" + pad(col.toString(16), 6, "0"); 23 | } 24 | function colorToRGB(col){ 25 | if(col==null)col = 0; 26 | var ret = []; 27 | ret[0] = ((col >> 16) & 0xff) / 0xff; 28 | ret[1] = ((col >> 8) & 0xff) / 0xff; 29 | ret[2] = (col & 0xff) / 0xff; 30 | return ret; 31 | } 32 | function rgbToColor(rgb){ 33 | return Math.round(rgb[0] * 0xff)<<16 | Math.round(rgb[1] * 0xff)<<8 | Math.round(rgb[2] * 0xff); 34 | } 35 | 36 | Dropdown.useNative = ($.os.indexOf("Win")==-1); 37 | 38 | if(Dropdown.useNative){ 39 | Dropdown.prototype={ 40 | onChange:null, 41 | 42 | init:function(container, items, selectedInd){ 43 | var scopedThis = this; 44 | 45 | this.dropdown = container.add("dropdownlist"); 46 | this.dropdown.onChange = function(){ 47 | scopedThis.onDropdownChange(); 48 | }; 49 | 50 | this.setItems(items); 51 | this.setSelection(selectedInd); 52 | }, 53 | onDropdownChange:function(){ 54 | if(this.selection == this.dropdown.selection.index) return; 55 | this.selection = this.dropdown.selection.index; 56 | if(this.onChange!=null) this.onChange(); 57 | }, 58 | setItems:function(items){ 59 | this.items = items; 60 | this.dropdown.removeAll(); 61 | if(items != null){ 62 | for(var i=0; i totalItems-1) selectedInd = totalItems-1; 80 | this.dropdown.selection = selectedInd; 81 | }, 82 | setEnabled:function(value){ 83 | this.dropdown.enabled = value; 84 | }, 85 | open:function(){ 86 | // Not supported 87 | }, 88 | close:function(){ 89 | // Not supported 90 | } 91 | }; 92 | 93 | }else{ 94 | 95 | Dropdown.prototype={ 96 | onChange:null, 97 | selection:-1, 98 | 99 | init:function(container, items, selectedInd){ 100 | var scopedThis = this; 101 | 102 | this.selection = -1; 103 | this.showing = false; 104 | 105 | this.group = container.add("group"); 106 | this.group.orientation = "row"; 107 | this.group.alignChildren = ["right", "center"]; 108 | this.group.margins = [0, 0, 0, 0]; 109 | this.group.spacing = 0; 110 | 111 | this.button = this.group.add('button'); 112 | //this.button.titleLayout = { margins: [5, 2, 2, 30] }; 113 | 114 | this.icon = this.group.add('iconbutton', undefined, ScriptUI.newImage (File(pack.directory+"/icons/dropdownArrow.png"))); 115 | 116 | /*this.button = container.add('iconbutton', undefined, ScriptUI.newImage (File(pack.directory+"/icons/dropdownArrow.png"))); 117 | this.button.title = "Testing"; 118 | this.button.titleLayout = { margins: [5, 2, 2, 3], alignment:["center", "center"] };*/ 119 | 120 | this.button.onClick = function(){ 121 | if(!scopedThis.showing){ 122 | scopedThis.open(); 123 | } 124 | } 125 | 126 | 127 | this.icon.onClick = this.button.onClick; 128 | 129 | this.listWindow = new Window("palette", undefined, undefined, {resizeable:false, closeButton:false, borderless:true}); 130 | 131 | this.listbox = this.listWindow.add ('ListBox', [0, 0, 10, 10], '', 132 | {numberOfColumns: 1, showHeaders: false, multiselect:false }); 133 | this.listbox.enabled = true; 134 | this.listbox.active = true; 135 | 136 | this.listbox.onChange = function(){ 137 | if(scopedThis.ignoreChanges) return; 138 | scopedThis.setSelection(scopedThis.listbox.selection.index); 139 | } 140 | 141 | this.listWindow.addEventListener("blur", function(){ 142 | if(scopedThis.showing) scopedThis.close(); 143 | }); 144 | 145 | this.button.window.addEventListener("move", function(){ 146 | if(scopedThis.showing) scopedThis.positionWindow(); 147 | }); 148 | 149 | this.setItems(items); 150 | this.setSelection(selectedInd); 151 | }, 152 | setItems:function(items){ 153 | this.items = items; 154 | this.listbox.removeAll(); 155 | var maxWidth = 0; 156 | var stackHeight = 0; 157 | if(items != null){ 158 | for(var i=0; i= 0) this.setSelection(this.selection); 188 | }, 189 | setSize:function(width, height){ 190 | this.width = width; 191 | this.button.size = [width-this.icon.preferredSize[0], height]; 192 | this.icon.size = [this.icon.preferredSize[0], height] 193 | }, 194 | positionWindow:function(){ 195 | //alert(this.button.window.frameLocation+"\n "+this.button.window.frameBounds+"\n"+this.button.window.frameSize+"\n"+this.button.window.bounds); 196 | var x = this.button.windowBounds[0] + this.button.window.bounds[0]; 197 | var y = this.button.windowBounds[3] + this.button.window.bounds[1] + 10; 198 | this.listWindow.frameLocation = [x, y]; 199 | }, 200 | setSelection:function(selectedInd){ 201 | this.close(); 202 | var max = (this.items==null ? -1 : this.items.length-1); 203 | if(selectedInd > max){ 204 | selectedInd = max; 205 | } 206 | if(this.selection == null) this.selection = -1; 207 | if(this.selection == selectedInd) return; 208 | 209 | 210 | this.selection = selectedInd; 211 | if(selectedInd == null || selectedInd == -1){ 212 | this.button.text = ""; 213 | }else{ 214 | var item = this.items[selectedInd]; 215 | this.button.text = item.label || item; 216 | } 217 | this.ignoreChanges = true; 218 | this.listbox.selection = this.items ? this.items[selectedInd] : null; 219 | this.ignoreChanges = false; 220 | 221 | try{ 222 | if(this.onChange != null) this.onChange(); 223 | }catch(e){ 224 | alert(e); 225 | } 226 | }, 227 | setEnabled:function(value){ 228 | if(!value && this.showing) close(); 229 | this.button.enabled = value; 230 | this.icon.enabled = value; 231 | }, 232 | open:function(){ 233 | this.showing = true; 234 | this.positionWindow(); 235 | this.listWindow.show(); 236 | this.listWindow.enabled = true; 237 | this.listbox.active = true; 238 | 239 | }, 240 | close:function(){ 241 | this.listWindow.enabled = false; 242 | this.listbox.active = false; 243 | this.showing = false; 244 | this.listWindow.hide(); 245 | 246 | } 247 | }; 248 | } 249 | pack.Dropdown = Dropdown; 250 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/PropertiesPanel.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | function PropertiesPanel(formatSettings){ 3 | this.init(formatSettings); 4 | return this; 5 | } 6 | PropertiesPanel.prototype={ 7 | 8 | controls:null, 9 | labelColumnW:130, 10 | 11 | init:function(formatSettings){ 12 | var scopedThis = this; 13 | 14 | var categories = formatSettings.formatRef.more; 15 | var doCatList = (categories.length>1); 16 | 17 | this.dialog = new Window('dialog', formatSettings.formatRef.name+" Settings"); 18 | this.dialog.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 19 | this.dialog.spacing = 9; 20 | 21 | this.formatSettings = formatSettings; 22 | 23 | var mainPanel; 24 | var firstPanel; 25 | if(doCatList){ 26 | 27 | this.labelColumnW = 180; 28 | 29 | firstPanel = this.dialog.add("group"); 30 | firstPanel.orientation = "column"; 31 | firstPanel.alignment = [ScriptUI.Alignment.RIGHT, ScriptUI.Alignment.TOP]; 32 | 33 | var row = this.dialog.add("group"); 34 | row.orientation = "row"; 35 | row.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 36 | 37 | this.catList = row.add ('ListBox', [0, 0, 160, 345], '', 38 | {numberOfColumns: 1, showHeaders: false, multiselect:false, 39 | columnTitles: ['Category'] }); 40 | this.catList.itemSize = [160, 42]; 41 | this.catList.orientation = "column"; 42 | this.catList.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]; 43 | for(var k=1; k 1 || !itemData.isGroup) return; 160 | 161 | var level = itemData.level + 1; 162 | if(itemData.childrenBuilt) 163 | { 164 | var childItems = itemData.childItems; 165 | for(var i=0; i 0); 196 | 197 | var item = parent.add(isGroup ? "node" : "item"); 198 | var index = this.indexOf(this.baseSelectedPaths, path); 199 | if(index != -1){ 200 | item.selected = true; 201 | this.baseSelectedPaths.splice(index, 1); 202 | } 203 | item.image = File(pack.directory+"/icons/checkbox_"+(item.selected?"":"un")+"selected.png"); 204 | 205 | if(pageItem.name == ""){ 206 | var type = pageItem.typename; 207 | if(type.lastIndexOf("Item") == type.length - 4){ 208 | type = type.substr(0, type.length - 4); 209 | } 210 | item.text += type + ": " + path; 211 | }else{ 212 | item.text = pageItem.name; 213 | } 214 | 215 | var index = this.indexOf(this.baseOpenPaths, path); 216 | var expanded = false; 217 | if(index != -1){ 218 | expanded = isGroup; 219 | this.baseOpenPaths.splice(index, 1); 220 | } 221 | 222 | var subItems = isLayer ? DocUtils.getAllPageItems(doc, pageItem, true) : pageItem.pageItems; 223 | 224 | var visible = parentVis && ((isLayer && pageItem.visible) || (!isLayer && !pageItem.hidden)); 225 | var itemData = { item:item, level:level, path:path, open:expanded, selected:item.selected, isGroup:isGroup, visible:visible, childrenBuilt:false, pageItems:subItems }; 226 | item.itemData = itemData; 227 | 228 | childItems.push( itemData ); 229 | this.items.push( itemData ); 230 | itemsHere.push( itemData ); 231 | 232 | if(isGroup){ 233 | if(expanded) openLevel = level; 234 | this.createTreeElements(itemData, openLevel); 235 | item.expanded = expanded; // Must be done after adding children 236 | } 237 | } 238 | }, 239 | onItemClick:function(item){ 240 | if(item == null || this.ignoreChanges) return; 241 | var data = item.itemData; 242 | data.selected = !data.selected; 243 | item.selected = data.selected; 244 | item.image = File(pack.directory+"/icons/checkbox_"+(data.selected?"":"un")+"selected.png"); 245 | this.checkSelection(); 246 | 247 | this.elementTree.selection = null; 248 | }, 249 | selectByLevel:function(select, level){ 250 | var rootItems = this.itemsByLevel[0]; 251 | this.ignoreChanges = true; 252 | for(var i=0; i.", 14 | DEFAULT_LAYER_PATTERN:"_.", 15 | DEFAULT_ELEMENT_PATTERN:"_.", 16 | DEFAULT_SYMBOL_PATTERN:".", 17 | 18 | type:ExportSettings, 19 | 20 | selectedTab:0, 21 | directory:"", 22 | formats:[], 23 | 24 | artboardAll:false, 25 | artboardInd:[], 26 | 27 | layerAll:false, 28 | layerInd:[], 29 | artboardAll_layers:true, 30 | artboardInd_layers:[], 31 | 32 | symbolAll:false, 33 | symbolNames:[], 34 | 35 | elementPaths:[], // e.g. ["layerInd : rootElemInd : childElemInd", "layerInd : rootElemInd : childElemInd"] 36 | elementOpenPaths:[], // e.g. ["layerInd : rootElemInd : childElemInd", "layerInd : rootElemInd : childElemInd"] 37 | artboardAll_elements:true, 38 | artboardInd_elements:[], 39 | 40 | //exportArtboards:false, 41 | ignoreWarnings:false, 42 | fontHandling:"none", 43 | 44 | ignoreOutOfBounds_layers:true, 45 | ignoreOutOfBounds_elements:true, 46 | 47 | 48 | toXML:function(includePatterns, includeGeneralSettings, includeFormatSettings, includeArtboards, includeLayers, includeElements, includeSymbols){ 49 | if(includeGeneralSettings===undefined)includeGeneralSettings = true; 50 | if(includeFormatSettings===undefined)includeFormatSettings = true; 51 | if(includeArtboards===undefined)includeArtboards = true; 52 | if(includeLayers===undefined)includeLayers = true; 53 | if(includeElements===undefined)includeElements = true; 54 | if(includeSymbols===undefined)includeSymbols = true; 55 | 56 | var ret = new XML( '' ); 57 | 58 | /*if(includePatterns){ 59 | ret.appendChild( new XML(''+this.xmlEncode(this.artboardPattern)+'') ); 60 | ret.appendChild( new XML(''+this.xmlEncode(this.layerPattern)+'') ); 61 | }*/ 62 | if(includeGeneralSettings){ 63 | ret.appendChild( new XML(''+this.selectedTab+'') ); 64 | ret.appendChild( new XML(''+this.directory+'') ); 65 | ret.appendChild( new XML(''+this.ignoreWarnings+'') ); 66 | ret.appendChild( new XML(''+this.ignoreOutOfBounds_layers+'') ); 67 | ret.appendChild( new XML(''+this.ignoreOutOfBounds_elements+'') ); 68 | } 69 | 70 | if(includeFormatSettings){ 71 | var formats = new XML(''); 72 | for(var i=0; i'+this.artboardInd+'') ); 81 | else ret.appendChild( new XML(''+this.artboardAll+'') ); 82 | } 83 | 84 | if(includeLayers){ 85 | if(!this.layerAll && this.layerInd.length) ret.appendChild( new XML(''+this.layerInd+'') ); 86 | else ret.appendChild( new XML(''+this.layerAll+'') ); 87 | if(!this.artboardAll_layers && this.artboardInd_layers.length) ret.appendChild( new XML(''+this.artboardInd_layers+'') ); 88 | else ret.appendChild( new XML(''+this.artboardAll_layers+'') ); 89 | } 90 | 91 | if(includeElements){ 92 | if(this.elementPaths.length){ 93 | ret.appendChild( new XML(''+this.elementPaths.join(",")+'') ); 94 | } 95 | if(this.elementOpenPaths.length){ 96 | ret.appendChild( new XML(''+this.elementOpenPaths.join(",")+'') ); 97 | } 98 | if(!this.artboardAll_elements && this.artboardInd_elements.length) ret.appendChild( new XML(''+this.artboardInd_elements+'') ); 99 | else ret.appendChild( new XML(''+this.artboardAll_elements+'') ); 100 | } 101 | 102 | if(includeSymbols){ 103 | if(!this.symbolAll && this.symbolNames.length)ret.appendChild( new XML(''+this.symbolNames+'') ); 104 | else ret.appendChild( new XML(''+this.symbolAll+'') ); 105 | } 106 | 107 | return ret; 108 | }, 109 | 110 | addNewFormat:function(formatSettings){ 111 | this.formats.push(formatSettings); 112 | 113 | var defaultPatterns = {}; 114 | var scaling; 115 | for(var i=this.formats.length-1; i>=0; --i){ 116 | var format = this.formats[i]; 117 | if(format.scaling)scaling = format.scaling; 118 | if(format==formatSettings)continue; 119 | for(var j in format.patterns){ 120 | if(!defaultPatterns[j])defaultPatterns[j] = format.patterns[j]; 121 | } 122 | } 123 | if(formatSettings.hasProp("scaling")){ 124 | formatSettings.scaling = scaling || 100; 125 | }else{ 126 | formatSettings.scaling = null; 127 | } 128 | if(!defaultPatterns.artboard) defaultPatterns.artboard = this.DEFAULT_ARTBOARD_PATTERN; 129 | if(!defaultPatterns.layer) defaultPatterns.layer = this.DEFAULT_LAYER_PATTERN; 130 | if(!defaultPatterns.element) defaultPatterns.element = this.DEFAULT_ELEMENT_PATTERN; 131 | if(!defaultPatterns.symbol) defaultPatterns.symbol = this.DEFAULT_SYMBOL_PATTERN; 132 | 133 | for(var j in defaultPatterns){ 134 | if(!formatSettings.patterns[j]) formatSettings.patterns[j] = defaultPatterns[j]; 135 | } 136 | }, 137 | 138 | populateWithXML:function(xml){ 139 | this.migrateXML(xml); 140 | 141 | //if(xml.artboardPattern.length())this.artboardPattern = xml.artboardPattern.toString() || this.DEFAULT_ARTBOARD_PATTERN; 142 | //if(xml.layerPattern.length())this.layerPattern = xml.layerPattern.toString() || this.DEFAULT_LAYER_PATTERN; 143 | if(xml.selectedTab.length())this.selectedTab = parseInt(xml.selectedTab.toString()); 144 | if(xml.directory.length())this.directory = xml.directory.toString(); 145 | if(xml.scaling.length())this.scaling = parseFloat( xml.scaling.toString().replace( /\% /, '' )); 146 | 147 | var defaultPatterns = {artboard:this.DEFAULT_ARTBOARD_PATTERN, layer:this.DEFAULT_LAYER_PATTERN, element:this.DEFAULT_ELEMENT_PATTERN, symbol:this.DEFAULT_SYMBOL_PATTERN}; 148 | var formatNodes = xml.formats.format; 149 | if(formatNodes.length()){ 150 | this.formats = []; 151 | for(var i=0; i"+node.suffix+"."; 299 | node.layerPattern = node.prefix+"_"+node.suffix+"."; 300 | delete node.prefix; 301 | delete node.suffix; 302 | } 303 | var base_path = node.base_path; 304 | if(base_path.length()){ 305 | node.directory = base_path.toString(); 306 | delete node.base_path; 307 | } 308 | var artboards = node.artboards; 309 | if(artboards.length()){ 310 | var artboards = artboards.toString(); 311 | if(artboards=="all"){ 312 | node.artboardAll = "true"; 313 | }else if(parseInt(artboards).toString()==artboards){ 314 | node.artboardInd = artboards; 315 | } 316 | delete node.artboards; 317 | } 318 | var layers = node.layers; 319 | if(layers.length()){ 320 | var layers = layers.toString(); 321 | if(layers=="all"){ 322 | node.layerAll = "true"; 323 | }else if(parseInt(layers).toString()==layers){ 324 | node.layerInd = layers; 325 | } 326 | delete node.layers; 327 | } 328 | if(node.elementPaths == null){ 329 | node.elementPaths = []; 330 | } 331 | if(node.elementOpenPaths == null){ 332 | node.elementOpenPaths = []; 333 | } 334 | var format = node.format; 335 | if(format.length()){ 336 | 337 | var formats = new XML(''); 338 | var formatNode = new XML(''); 339 | 340 | formatNode.format = node.format; 341 | formatNode.transparency = node.transparency; 342 | formatNode.embedImage = node.embedImage; 343 | formatNode.fontHandling = (node.embedFont?"embed":"none"); 344 | formatNode.trimEdges = node.trimEdges; 345 | formatNode.innerPadding = node.innerPadding; 346 | 347 | formats.appendChild(formatNode); 348 | node.appendChild(formats); 349 | 350 | delete node.format; 351 | delete node.transparency; 352 | delete node.embedImage; 353 | delete node.embedFont; 354 | delete node.trimEdges; 355 | delete node.innerPadding; 356 | } 357 | var formats = node.formats.format; 358 | if(formats.length()){ 359 | for(var i=0; i")); 363 | } 364 | if(node.artboardPattern.length() && formatNode.patterns.artboard.length()==0){ 365 | formatNode.patterns.artboard = node.artboardPattern.toString(); 366 | } 367 | if(node.layerPattern.length() && formatNode.patterns.layer.length()==0){ 368 | formatNode.patterns.layer = node.layerPattern.toString(); 369 | } 370 | if(node.scaling && formatNode.scaling.length()==0){ 371 | formatNode.scaling = node.scaling.toString(); 372 | } 373 | if(formatNode.trimEdges && formatNode.trimEdges.length()!=0){ 374 | var trim = formatNode.trimEdges.toString() == 'true'; 375 | if(formatNode.boundsMode.length() == 0){ 376 | formatNode.boundsMode = trim ? pack.BoundsMode.ARTBOARD_AND_ARTWORK : pack.BoundsMode.ARTBOARD; 377 | } 378 | delete formatNode.trimEdges; 379 | } 380 | } 381 | delete node.artboardPattern; 382 | delete node.layerPattern; 383 | delete node.scaling; 384 | } 385 | }/*, 386 | xmlEncode:function(str){ 387 | str = str.split("&").join("&"); 388 | str = str.split("<").join("<"); 389 | str = str.split(">").join(">"); 390 | str = str.split('"').join("""); 391 | str = str.split("'").join("'"); 392 | return str; 393 | }*/ 394 | }; 395 | pack.ExportSettings = ExportSettings; 396 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/LayerBundler.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | LayerBundler = {}; 3 | 4 | LayerBundler.NO_COPY = "noCopy"; 5 | 6 | 7 | LayerBundler.addElements = function(docRef, bundles, exportSettings, patternName, hasBoundErrorRef, elemVis){ 8 | 9 | LayerBundler.hasBoundErrorRef = hasBoundErrorRef; 10 | 11 | 12 | var artboardInd = exportSettings.artboardInd_elements; 13 | var elementPaths = exportSettings.elementPaths; 14 | 15 | var hasExports = false; 16 | 17 | if(!elementPaths.length)return; 18 | 19 | for (var i = 0; i < artboardInd.length; i++ ) { 20 | var artI = artboardInd[i]; 21 | if(artI >= docRef.artboards.length)continue; 22 | var artboard = docRef.artboards[artI]; 23 | 24 | for ( var j=0; j < elementPaths.length; j++ ) { 25 | var path = elementPaths[j]; 26 | var pathParts = path.split(":"); 27 | var layI = parseInt(pathParts[0]) - 1; 28 | if(layI >= docRef.layers.length)continue; 29 | 30 | var layer = docRef.layers[layI]; 31 | 32 | var layerPath = (layI + 1) + ""; 33 | 34 | var element; 35 | var searchPath; 36 | if(layerPath == path){ 37 | element = layer; 38 | }else{ 39 | searchPath = path; 40 | element = LayerBundler.findElement(layerPath, layer.pageItems, path); 41 | if(element == null) continue; 42 | } 43 | 44 | var bundleMap = {}; 45 | 46 | for (var x = 0; x < exportSettings.formats.length; x++ ) { 47 | var formatSettings = exportSettings.formats[x]; 48 | var filePattern = formatSettings.patterns[patternName]; 49 | if(!formatSettings.active || filePattern == "" || filePattern == null) continue; 50 | 51 | var format = formatSettings.formatRef; 52 | 53 | 54 | var bundle = this.getBundle(bundleMap, artI, layI, formatSettings.innerPadding, formatSettings.scaling, formatSettings.boundsMode, format.copyBehaviour, formatSettings.fontHandling=="outline", exportSettings.ignoreOutOfBounds_elements, formatSettings.ungroup, j==0, j==elementPaths.length-1, elemVis, formatSettings.colorSpace, formatSettings.rasterResolution, searchPath); 55 | var elemName = (element.name || path); 56 | var name = LayerBundler.makeElemFileName(filePattern, docRef.fullName.name, formatSettings.formatRef.ext, artI, artboard.name, layI, layer.name, path, elemName); 57 | var item = new pack.ExportItem(formatSettings, name); 58 | item.names = ["Artboard "+(artI+1), "Element "+path]; 59 | bundle.items.push(item); 60 | 61 | hasExports = true; 62 | } 63 | 64 | for(var k in bundleMap){ 65 | bundle = bundleMap[k]; 66 | if(bundle.items.length){ 67 | bundles.push(bundle); 68 | } 69 | } 70 | } 71 | } 72 | return hasExports; 73 | } 74 | LayerBundler.addLayers = function(docRef, bundles, exportSettings, patternName, hasBoundErrorRef, elemVis){ 75 | 76 | LayerBundler.hasBoundErrorRef = hasBoundErrorRef; 77 | 78 | var artboardInd = exportSettings.artboardInd_layers; 79 | var layerInd = exportSettings.layerInd; 80 | 81 | var hasExports = false; 82 | 83 | if(!layerInd.length)return; 84 | 85 | for (var i = 0; i < artboardInd.length; i++ ) { 86 | var artI = artboardInd[i]; 87 | if(artI >= docRef.artboards.length)continue; 88 | var artboard = docRef.artboards[artI]; 89 | 90 | for ( var j=0; j < layerInd.length; j++ ) { 91 | var layI = layerInd[j]; 92 | if(layI >= docRef.layers.length)continue; 93 | 94 | var layer = docRef.layers[layI]; 95 | 96 | var bundleMap = {}; 97 | 98 | for (var x = 0; x < exportSettings.formats.length; x++ ) { 99 | var formatSettings = exportSettings.formats[x]; 100 | var filePattern = formatSettings.patterns[patternName]; 101 | if(!formatSettings.active || filePattern == '' || filePattern == null) continue; 102 | 103 | var format = formatSettings.formatRef; 104 | 105 | 106 | var bundle = this.getBundle(bundleMap, artI, layI, formatSettings.innerPadding, formatSettings.scaling, formatSettings.boundsMode, format.copyBehaviour, formatSettings.fontHandling=="outline", exportSettings.ignoreOutOfBounds_layers, formatSettings.ungroup, j==0, j==layerInd.length-1, elemVis, formatSettings.colorSpace, formatSettings.rasterResolution); 107 | var item = new pack.ExportItem(formatSettings, LayerBundler.makeFileName(filePattern, docRef.fullName.name, formatSettings.formatRef.ext, artI, artboard.name, layI, layer.name)); 108 | item.names = ["Artboard "+(artI+1), "Layer "+(layI+1)]; 109 | bundle.items.push(item); 110 | 111 | hasExports = true; 112 | } 113 | 114 | for(var k in bundleMap){ 115 | bundle = bundleMap[k]; 116 | if(bundle.items.length){ 117 | bundles.push(bundle); 118 | } 119 | } 120 | } 121 | } 122 | return hasExports; 123 | } 124 | LayerBundler.getBundle = function(bundleMap, artI, layI, padding, scaling, boundsMode, forceCopy, doOutline, ignoreOutOfBounds, ungroup, isFirst, isLast, elemVis, colorSpace, rasterResolution, elemPath){ 125 | // TODO: Remove 'elemPath' from this check after testing it using show/hide & reused doc methods 126 | var trim = boundsMode != pack.BoundsMode.ARTBOARD; 127 | if(trim || doOutline || padding || colorSpace) forceCopy = true; 128 | 129 | var key; 130 | if(!forceCopy){ 131 | key = this.NO_COPY; 132 | }else{ 133 | key = boundsMode+"_"+(doOutline?"outline":"nooutline")+"_"+(padding?"pad":"nopad")+(ungroup?"_ungroup":"") + (colorSpace==null ? "" : "_"+colorSpace) + (rasterResolution==null ? "" : "_"+rasterResolution) + (elemPath==null ? "" : "_"+elemPath); 134 | } 135 | var bundle = bundleMap[key]; 136 | if(bundle){ 137 | return bundle; 138 | 139 | }else if(!forceCopy){ 140 | // export types which don't require a new document to be created just show/hide layers to complete export. (No pad, no trim, raster exports) 141 | bundle = new pack.ExportBundle(); 142 | bundle.prepareHandler = isFirst ? closure(LayerBundler, LayerBundler.prepareShowLayerFirst, [artI, layI, elemPath], true) : closure(LayerBundler, LayerBundler.prepareShowLayer, [artI, layI, elemPath], true); 143 | bundle.cleanupHandler = isLast ? closure(LayerBundler, LayerBundler.cleanupShowLayerLast, [elemVis, layI], true) : closure(LayerBundler, LayerBundler.cleanupShowLayer, [elemVis, artI, layI, elemPath], true); 144 | 145 | }else if(!trim){ 146 | // non-trimmed export types can simply create a new document once for each artboard. (no trim, vector exports) 147 | bundle = new pack.ExportBundle(); 148 | bundle.prepareHandler = isFirst ? closure(LayerBundler, LayerBundler.prepareCopyDoc, [artI, layI, padding, doOutline, ignoreOutOfBounds, ungroup, elemVis, colorSpace, rasterResolution, elemPath, boundsMode], true) : closure(LayerBundler, LayerBundler.prepareCopyLayer, [artI, layI, padding, doOutline, ignoreOutOfBounds, ungroup, false, elemVis, null, colorSpace, rasterResolution, elemPath, boundsMode], true); 149 | bundle.cleanupHandler = isLast ? LayerBundler.cleanupCopyDoc : LayerBundler.cleanupCopyLayer; 150 | 151 | }else{ 152 | // trimmed export types must create a new document for each artboard/layer/elem pair. (No pad, trim, vector exports) 153 | bundle = new pack.ExportBundle(); 154 | bundle.prepareHandler = closure(LayerBundler, LayerBundler.prepareCopyLayer, [artI, layI, padding, doOutline, ignoreOutOfBounds, ungroup, true, elemVis, null, colorSpace, rasterResolution, elemPath, boundsMode], true); 155 | bundle.cleanupHandler = LayerBundler.cleanupCopyDoc; 156 | 157 | } 158 | bundleMap[key] = bundle; 159 | return bundle; 160 | } 161 | 162 | LayerBundler.prepareCopyDoc = function(docRef, exportSettings, exportBundle, artI, layI, padding, doOutline, ignoreOutOfBounds, ungroup, elemVis, colorSpace, rasterResolution, elemPath, boundsMode){ 163 | var artboard = docRef.artboards[artI]; 164 | docRef.artboards.setActiveArtboardIndex(artI); 165 | 166 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM; 167 | var rect = artboard.artboardRect; 168 | var artW = rect[2]-rect[0]; 169 | var artH = rect[1]-rect[3]; 170 | 171 | //var offset = {x:0, y:0}; 172 | LayerBundler.layerDepths = []; 173 | LayerBundler.copyDoc = pack.DocUtils.copyDocument(docRef, artboard, rect, artW, artH, padding, pack.DocUtils.isAdditionalLayer, LayerBundler.layerDepths, doOutline, ungroup, elemVis, exportSettings.ignoreWarnings, LayerBundler.hasBoundErrorRef, null, colorSpace, rasterResolution); 174 | LayerBundler.hasAdditLayers = LayerBundler.copyDoc.layers.length > 0 && (LayerBundler.copyDoc.layers.length!=1 || LayerBundler.copyDoc.layers[0].pageItems.length || LayerBundler.copyDoc.layers[0].layers.length); 175 | return this.prepareCopyLayer(docRef, exportSettings, exportBundle, artI, layI, padding, doOutline, ignoreOutOfBounds, ungroup, false, elemVis, rect, colorSpace, rasterResolution, elemPath, boundsMode); 176 | } 177 | LayerBundler.prepareCopyLayer = function(docRef, exportSettings, exportBundle, artI, layI, padding, doOutline, ignoreOutOfBounds, ungroup, createDoc, elemVis, rect, colorSpace, rasterResolution, elemPath, boundsMode){ 178 | //docRef.artboards.setActiveArtboardIndex(artI); // throws an error if new doc has already been created (can't change artboard when doc isn't in focus) 179 | var doc = LayerBundler.copyDoc || docRef; 180 | 181 | if(LayerBundler.copyDoc) app.activeDocument = docRef; // can't access artboard props when owner doc isn't in focus 182 | var layer = docRef.layers[layI]; 183 | var artboard = docRef.artboards[artI]; 184 | if(!rect){ 185 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM; 186 | rect = artboard.artboardRect; 187 | } 188 | var artboardName = artboard.name; 189 | 190 | if(LayerBundler.copyDoc)app.activeDocument = doc; 191 | 192 | var elemFilter = (elemPath == null ? null : closure(LayerBundler, LayerBundler.filterElements, [elemPath], true)); 193 | if(elemFilter == null && boundsMode == pack.BoundsMode.ARTWORK) elemFilter = closure(LayerBundler, ungroup ? LayerBundler.filterByVisibleUngroup : LayerBundler.filterByVisible, [], true); 194 | 195 | // only process layer if it has bounds (i.e. not guide layer) and falls within current artboard bounds 196 | var layerRect = pack.DocUtils.getLayerBounds(docRef, layer, null, elemFilter); 197 | if (layerRect) { 198 | var isVis = boundsMode == pack.BoundsMode.ARTWORK || (!ignoreOutOfBounds || pack.DocUtils.intersects(rect, layerRect)); 199 | if((createDoc || !LayerBundler.hasAdditLayers) && !isVis){ 200 | // skip layers where nothing is visible 201 | return "skipped"; 202 | } 203 | if(createDoc){ 204 | 205 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM; 206 | 207 | var layerOffsetX = 0; 208 | var layerOffsetY = 0; 209 | 210 | // crop to artboard 211 | if(boundsMode == pack.BoundsMode.ARTBOARD_AND_ARTWORK){ 212 | if(layerRect[0]rect[1]){ 216 | layerRect[1] = rect[1]; 217 | } 218 | if(layerRect[2]>rect[2]){ 219 | layerRect[2] = rect[2]; 220 | } 221 | if(layerRect[3] 0 && (doc.layers.length!=1 || doc.layers[0].pageItems.length || doc.layers[0].layers.length); 238 | }else{ 239 | layOffset = null; 240 | } 241 | if(isVis){ 242 | // only copy layer if it is visible (if not only visible '+' layers will be output) 243 | var artb = doc.artboards[0]; 244 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM; 245 | var new_layer = pack.DocUtils.copyLayer(docRef, LayerBundler.copyDoc, artb, LayerBundler.copyDoc.artboards[0], rect, layer, doc.layers.add(), padding, doOutline, ungroup, docRef.rulerOrigin, exportSettings.ignoreWarnings, LayerBundler.hasBoundErrorRef, layOffset, elemFilter); 246 | new_layer.visible = true; 247 | var depth = LayerBundler.layerDepths[layI]; 248 | pack.DocUtils.setLayerDepth(new_layer, depth); 249 | exportBundle.copyLayer = new_layer; 250 | } 251 | return doc; 252 | } 253 | 254 | return null; 255 | } 256 | LayerBundler.filterElements = function(element, path, matchPath){ 257 | if(matchPath == path){ 258 | return true; 259 | }else if(matchPath.indexOf(path) == 0){ 260 | return 'explore'; 261 | } 262 | return false; 263 | } 264 | LayerBundler.filterByVisibleUngroup = function(element, path){ 265 | if(element.hidden){ 266 | return false; 267 | }else{ 268 | return 'explore'; 269 | } 270 | } 271 | LayerBundler.filterByVisible = function(element, path){ 272 | if(element.hidden){ 273 | return false; 274 | }else{ 275 | return true; 276 | } 277 | } 278 | LayerBundler.prepareShowLayerFirst = function(docRef, exportSettings, exportBundle, artI, layI, elemPath){ 279 | pack.DocUtils.hideAllLayers(docRef); 280 | 281 | exportBundle.hasOrigAdditLayers = false; 282 | for(var i=0; i 1){ 193 | this.tabPanel = new pack.MainTabbedPanel( this.toolPanel, 160, 480 ); 194 | this.tabPanel.onChange = function(byUser){ 195 | if(byUser){ 196 | exSettings.selectedTab = scopedThis.tabPanel.selection; 197 | } 198 | } 199 | } 200 | 201 | if(showParts.layers){ 202 | var tab = this.tabPanel ? this.tabPanel.add("Layers") : this.toolPanel.add("panel"); 203 | tab.orientation = "row"; 204 | 205 | this.artboardPanel_layers = new pack.ArtboardPanel(tab, exSettings.artboardAll_layers, exSettings.artboardInd_layers, true); 206 | this.artboardPanel_layers.onSelectedChanged = function() { 207 | exSettings.artboardAll_layers = scopedThis.artboardPanel_layers.selectAll; 208 | exSettings.artboardInd_layers = scopedThis.artboardPanel_layers.selectedIndices; 209 | scopedThis.updatePreviewList(); 210 | }; 211 | this.artboardPanel_layers.onSelectedChanged(); 212 | 213 | this.layerPanel = new pack.LayerPanel(tab, exSettings.layerAll, exSettings.layerInd, pack.IGNORE_LAYERS, exSettings.ignoreOutOfBounds_layers); 214 | this.layerPanel.onSelectedChanged = function() { 215 | exSettings.layerAll = scopedThis.layerPanel.selectAll; 216 | exSettings.layerInd = scopedThis.layerPanel.selectedIndices; 217 | scopedThis.updatePreviewList(); 218 | }; 219 | this.layerPanel.onIgnoreOutOfBoundsChanged = function() { 220 | exSettings.ignoreOutOfBounds_layers = scopedThis.layerPanel.ignoreOutOfBounds; 221 | }; 222 | } 223 | 224 | if(showParts.artboards){ 225 | var tab = this.tabPanel ? this.tabPanel.add("Artboards") : this.toolPanel.add("panel"); 226 | tab.orientation = "row"; 227 | 228 | this.artboardPanel = new pack.ArtboardPanel(tab, exSettings.artboardAll, exSettings.artboardInd); 229 | this.artboardPanel.onSelectedChanged = function() { 230 | exSettings.artboardAll = scopedThis.artboardPanel.selectAll; 231 | exSettings.artboardInd = scopedThis.artboardPanel.selectedIndices; 232 | scopedThis.updatePreviewList(); 233 | }; 234 | this.artboardPanel.onSelectedChanged(); 235 | } 236 | 237 | if(showParts.elements){ 238 | var tab = this.tabPanel ? this.tabPanel.add("Elements") : this.toolPanel.add("panel"); 239 | tab.orientation = "row"; 240 | 241 | this.artboardPanel_elements = new pack.ArtboardPanel(tab, exSettings.artboardAll_elements, exSettings.artboardInd_elements, true); 242 | this.artboardPanel_elements.onSelectedChanged = function() { 243 | exSettings.artboardAll_elements = scopedThis.artboardPanel_elements.selectAll; 244 | exSettings.artboardInd_elements = scopedThis.artboardPanel_elements.selectedIndices; 245 | scopedThis.updatePreviewList(); 246 | }; 247 | this.artboardPanel_elements.onSelectedChanged(); 248 | 249 | this.elementPanel = new pack.ElementPanel(tab, exSettings.elementPaths, exSettings.elementOpenPaths, pack.IGNORE_LAYERS, exSettings.ignoreOutOfBounds_elements); 250 | this.elementPanel.onSelectedChanged = function() { 251 | exSettings.elementPaths = scopedThis.elementPanel.selectedPaths; 252 | exSettings.elementOpenPaths = scopedThis.elementPanel.openPaths; 253 | scopedThis.updatePreviewList(); 254 | }; 255 | this.elementPanel.onOpenedChanged = function() { 256 | exSettings.elementOpenPaths = scopedThis.elementPanel.openPaths; 257 | }; 258 | this.elementPanel.onIgnoreOutOfBoundsChanged = function() { 259 | exSettings.ignoreOutOfBounds_elements = scopedThis.elementPanel.ignoreOutOfBounds; 260 | }; 261 | 262 | if(this.tabPanel) this.tabPanel.setTransHandlers(this.tabPanel.panels.length - 1, closure(this.elementPanel, this.elementPanel.show)); 263 | else this.elementPanel.show(); 264 | } 265 | 266 | if(showParts.symbols){ 267 | var tab = this.tabPanel ? this.tabPanel.add("Symbols") : this.toolPanel.add("panel"); 268 | tab.orientation = "row"; 269 | 270 | this.symbolPanel = new pack.SymbolPanel(tab, exSettings.symbolAll, exSettings.symbolNames); 271 | this.symbolPanel.onSelectedChanged = function() { 272 | exSettings.symbolAll = scopedThis.symbolPanel.selectAll; 273 | exSettings.symbolNames = scopedThis.symbolPanel.selectedNames; 274 | scopedThis.updatePreviewList(); 275 | }; 276 | } 277 | 278 | if(showParts.formats){ 279 | var tab = this.tabPanel ? this.tabPanel.add("Export Settings", pack.Button.STYLE_MAIN_TAB_OUTPUT) : this.toolPanel.add("panel"); 280 | var settingsCol = tab; 281 | 282 | var column; 283 | var row; 284 | 285 | this.settingsPanel = new pack.SettingsPanel(settingsCol, this.exportSettings); 286 | this.settingsPanel.onPatternChanged = function(){ 287 | scopedThis.updatePreviewList(); 288 | } 289 | 290 | this.formatPanel = new pack.FormatPanel(settingsCol, pack.formats, this.exportSettings); 291 | this.formatPanel.onFormatsChanged = function(){ 292 | scopedThis.updatePreviewList(); 293 | } 294 | } 295 | 296 | 297 | if(showParts.preview){ 298 | var tab = this.tabPanel ? this.tabPanel.add("Output Files", pack.Button.STYLE_MAIN_TAB_OUTPUT) : this.toolPanel.add("panel"); 299 | this.previewPanel = new pack.PreviewFilesPanel(tab); 300 | 301 | if(this.tabPanel){ 302 | this.outputTabIndex = this.tabPanel.panels.length - 1; 303 | this.tabPanel.setTransHandlers(this.outputTabIndex, closure(this.previewPanel, this.previewPanel.show), closure(this.previewPanel, this.previewPanel.hide)); 304 | }else this.previewPanel.show(); 305 | } 306 | 307 | if(showParts.progress){ 308 | // progress bar 309 | this.progBar = this.toolPanel.add( 'progressbar', undefined, 0, 100 ); 310 | this.progBar.alignment = [ScriptUI.Alignment.RIGHT, ScriptUI.Alignment.TOP]; 311 | this.progBar.size = [665,10]; 312 | } 313 | 314 | if(showParts.exportButtons){ 315 | this.exportPanel = new pack.ExportPanel(this.toolPanel, this.exportSettings); 316 | this.exportPanel.onCancelClicked = function() { 317 | if(scopedThis.exporter.running){ 318 | scopedThis.exporter.cancel(); 319 | }else{ 320 | scopedThis.toolPanel.close(); 321 | } 322 | }; 323 | this.exportPanel.onSaveCloseClicked = function() { 324 | scopedThis.saveOptions(); 325 | scopedThis.toolPanel.close() 326 | }; 327 | this.exportPanel.onExportClicked = closure(this, this.beginExport); 328 | } 329 | 330 | this.exporter = new pack.Exporter(this.exportSettings, 331 | function(prog, total){scopedThis.setProgress(prog, total)}, 332 | function(item){scopedThis.previewPanel.updatedExportItem(item); scopedThis.toolPanel.update();}); 333 | 334 | this.exporter.onExportFinished = function(success, fail){ 335 | if(success){ 336 | scopedThis.toolPanel.close(); 337 | } 338 | } 339 | 340 | 341 | this.elemVis = pack.DocUtils.getAllElemVisibility(this.docRef); 342 | 343 | if(this.artboardPanel) this.artboardPanel.onSelectedChanged(); 344 | if(this.layerPanel) this.layerPanel.onSelectedChanged(); 345 | if(this.elementPanel) this.elementPanel.onSelectedChanged(); 346 | if(this.symbolPanel) this.symbolPanel.onSelectedChanged(); 347 | 348 | if(this.tabPanel) this.tabPanel.setSelection(exSettings.selectedTab); 349 | 350 | this.finishedBuilding = true; 351 | this.updatePreviewList(); 352 | 353 | if(this.autoExport){ 354 | this.toolPanel.onActivate = function(e){ 355 | scopedThis.toolPanel.onActivate = null; 356 | scopedThis.beginExport(false); 357 | } 358 | } 359 | 360 | this.toolPanel.show(); 361 | }, 362 | 363 | beginExport:function(save) { 364 | if(save == null) save = true; 365 | try{ 366 | this.hasBoundErrorRef.broken = 0; 367 | if(save) this.saveOptions(); // save options before export in case of errors 368 | 369 | var dir = this.exportSettings.directory || ""; 370 | if($.os.toLowerCase().indexOf("mac")!=-1){ 371 | if(dir.charAt(0)!="/"){ 372 | dir = this.docRef.path + "/" + dir; 373 | } 374 | }else{ 375 | if(dir.indexOf(":")==-1){ 376 | dir = this.docRef.path + "\\" + dir; 377 | } 378 | } 379 | var ran = this.exporter.checkValid(this.bundleList, this.exportSettings, dir); 380 | if(ran){ 381 | if(this.tabPanel) this.tabPanel.setSelection(this.outputTabIndex); 382 | this.exporter.doRun(); 383 | if(this.hasBoundErrorRef.broken){ 384 | var layerName = ( this.hasBoundErrorRef.broken==1 ? "A layer" : this.hasBoundErrorRef.broken+" layers"); 385 | alert(layerName+" couldn't be positioned correctly due to an Illustrator bug, if there are alignment problems in the exported files please export again with warnings turned on.\n\nYou'll have to click through warnings but the exports should be aligned properly."); 386 | } 387 | } 388 | }catch(e){ 389 | alert("Error running export: "+e); 390 | } 391 | }, 392 | 393 | setProgress:function(prog, total){ 394 | if(!this.progBar) return; 395 | this.progBar.value = prog / total * 100; 396 | }, 397 | 398 | updatePreviewList:function(){ 399 | if(!this.finishedBuilding) return; 400 | try{ 401 | this.bundleList = []; 402 | this.hasBoundErrorRef = {}; 403 | 404 | var hasExports = pack.ArtboardBundler.add(this.docRef, this.bundleList, this.exportSettings, "artboard", this.hasBoundErrorRef); 405 | if(this.formatPanel) this.formatPanel.setPatternActive("artboard", hasExports); 406 | 407 | var hasExports = pack.LayerBundler.addLayers(this.docRef, this.bundleList, this.exportSettings, "layer", this.hasBoundErrorRef, this.elemVis); 408 | if(this.formatPanel) this.formatPanel.setPatternActive("layer", hasExports); 409 | 410 | var hasExports = pack.LayerBundler.addElements(this.docRef, this.bundleList, this.exportSettings, "element", this.hasBoundErrorRef, this.elemVis); 411 | if(this.formatPanel) this.formatPanel.setPatternActive("element", hasExports); 412 | 413 | var hasExports = pack.SymbolBundler.add(this.docRef, this.bundleList, this.exportSettings, "symbol"); 414 | if(this.formatPanel) this.formatPanel.setPatternActive("symbol", hasExports); 415 | 416 | var windowsFS = (Folder.fs=="Windows"); 417 | if(windowsFS){ 418 | for(var i=0; i").join("-"); 429 | path = path.split('"').join("'"); 430 | path = path.split(':').join(";"); 431 | item.fileName = path; 432 | } 433 | } 434 | }else{ 435 | for(var i=0; i=selectList.length){ 475 | return index-selectList.length; 476 | }else{ 477 | return selectList[index].code; 478 | } 479 | }, 480 | 481 | saveOptions:function(){ 482 | var exSettings = this.exportSettings; 483 | 484 | this.smartExportPrefs.textFrames[0].contents = exSettings.toXML().toXMLString(); 485 | this.smartExportPrefs.name = this.prefsLayerName; 486 | } 487 | }; 488 | pack.ExportToolBuilder = ExportToolBuilder; 489 | })(smartExport) -------------------------------------------------------------------------------- /SmartCore/DocUtils.jsx: -------------------------------------------------------------------------------- 1 | (function(pack){ 2 | DocUtils = {}; 3 | 4 | 5 | 6 | DocUtils.copyDocument = function(docRef, artboard, artboardRect, w, h, doInnerPadding, layerCheck, layerDepths, outlineText, ungroup, layerVis, ignoreWarnings, hasBoundErrorRef, offset, colorSpace, rasterResolution) { 7 | if(w<1)w = 1; 8 | if(h<1)h = 1; 9 | var preset = new DocumentPreset(); 10 | preset.width = w; 11 | preset.height = h; 12 | preset.units = docRef.rulerUnits; 13 | 14 | if(rasterResolution == "screen"){ 15 | preset.rasterResolution = DocumentRasterResolution.ScreenResolution; 16 | }else if(rasterResolution == "medium"){ 17 | preset.rasterResolution = DocumentRasterResolution.MediumResolution; 18 | }else{ 19 | preset.rasterResolution = DocumentRasterResolution.HighResolution; 20 | } 21 | 22 | if(colorSpace == "cmyk"){ 23 | preset.colorMode = DocumentColorSpace.CMYK; 24 | }else if(colorSpace == "rgb"){ 25 | preset.colorMode = DocumentColorSpace.RGB; 26 | }else{ 27 | preset.colorMode = docRef.documentColorSpace; 28 | } 29 | 30 | var copyDoc = app.documents.addDocument(preset.colorMode, preset); 31 | copyDoc.artboards.setActiveArtboardIndex(0); 32 | var copyArtboard = copyDoc.artboards[0]; 33 | copyArtboard.shift = null; // Illustrator seems to reuse instances behind the scenes 34 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM; 35 | copyDoc.isNew = true; 36 | try{ 37 | //app.activeDocument = docRef; // this allows us to do the selection trick when copying layers 38 | 39 | // for some mystical reason, setting these can mess up the artboard dimensions 40 | //copyDoc.pageOrigin = docRef.pageOrigin; 41 | //copyDoc.rulerOrigin = docRef.rulerOrigin; 42 | 43 | var count = 1; // indices are 1 based! 44 | var n = docRef.layers.length; 45 | for ( var j=docRef.layers.length-1; j >= 0; j-- ) { 46 | layer = docRef.layers[j]; 47 | 48 | var vis = (layerVis ? layerVis[j] : layer.visible ); 49 | if (layerCheck==null || layerCheck(layer, vis)) { 50 | //var layerBounds = this.getLayerBounds(docRef, layer); 51 | //if(layerBounds && this.intersects(artboardRect, layerBounds)){ 52 | var newLayer = this.copyLayer(docRef, copyDoc, artboard, copyArtboard, artboardRect, layer, copyDoc.layers.add(), doInnerPadding, outlineText, ungroup, docRef.rulerOrigin, ignoreWarnings, hasBoundErrorRef, offset); 53 | this.setLayerDepth(newLayer, count); 54 | if(!newLayer.pageItems.length && !newLayer.layers.length){ 55 | newLayer.remove(); 56 | }else{ 57 | ++count; 58 | } 59 | //} 60 | }else if(layerDepths){ 61 | layerDepths[j] = count; 62 | } 63 | } 64 | 65 | return copyDoc; 66 | }catch(e){ 67 | alert("DocUtils.copyDocument failed:\n"+e); 68 | copyDoc.close(SaveOptions.DONOTSAVECHANGES); 69 | } 70 | } 71 | DocUtils.rectEqual = function(rect1, rect2) { 72 | return rect1[0]==rect2[0] && rect1[1]==rect2[1] && rect1[2]==rect2[2] && rect1[3]==rect2[3] ; 73 | } 74 | 75 | DocUtils.getArtboardShift = function(artboardRect, toArtboard) { 76 | var toRect = toArtboard.artboardRect; 77 | return {x:toRect[0] - artboardRect[0], y:toRect[3] - artboardRect[3]}; 78 | } 79 | 80 | DocUtils.getLayerIndex = function(layers, layer){ 81 | for(var i=0; i=0; --j){ 157 | var child = children[j]; 158 | child.move(item, ElementPlacement.PLACEAFTER); 159 | this.doUngroupItem(child); 160 | } 161 | item.remove(); 162 | } 163 | } 164 | DocUtils.getLayerBounds = function(doc, layer, artboardRect, elemFilter, parentPath) { 165 | var rect; 166 | var items = DocUtils.getAllPageItems(doc, layer, true); 167 | 168 | if(parentPath == null) parentPath = (DocUtils.getLayerIndex(doc.layers, layer) + 1) + ""; 169 | parentPath += ":"; 170 | 171 | var childFilter = elemFilter; 172 | for(var i=0; iitemBounds[0]){ 204 | rect[0] = itemBounds[0]; 205 | } 206 | if(rect[1]itemBounds[3]){ 213 | rect[3] = itemBounds[3]; 214 | } 215 | } 216 | } 217 | 218 | if(rect && rect[0]rect[3]){ 219 | return rect; 220 | }else{ 221 | return null; 222 | } 223 | } 224 | 225 | DocUtils.artboardIntersects = function(docRef, artI, rect){ 226 | var artboard = docRef.artboards[artI]; 227 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM; 228 | var artRect = artboard.artboardRect; 229 | return this.intersects(artRect, rect); 230 | } 231 | 232 | DocUtils.copyIntoLayer = function(doc, fromLayer, toLayer, ignoreWarnings, artboardRect, parentPath, elemFilter) { 233 | var items = this.getAllPageItems(doc, fromLayer, ignoreWarnings); 234 | try{ 235 | this.copyItems(doc, items, toLayer, ignoreWarnings, artboardRect, parentPath, elemFilter); 236 | }catch(e){ 237 | alert("Copy items failed: "+e); 238 | } 239 | } 240 | 241 | DocUtils.copyItems = function(doc, fromList, toLayer, ignoreWarnings, artboardRect, parentPath, elemFilter) { 242 | parentPath += ":"; 243 | var visWas = toLayer.visible; 244 | toLayer.visible = true; 245 | for(var i=0; idepth){ 324 | layer.zOrder(ZOrderMethod.SENDBACKWARD); 325 | } 326 | } 327 | 328 | DocUtils.intersects = function(rect1, rect2) { 329 | return !( rect2[0] > rect1[2] || 330 | rect2[1] < rect1[3] || 331 | rect2[2] < rect1[0] || 332 | rect2[3] > rect1[1]); 333 | } 334 | 335 | var setGetVisiblity = function(visState, doc, elems, path, ignoreWarnings, isSetting){ 336 | if(path == null) path = ""; 337 | else path += ":"; 338 | 339 | for(var i=0; i=0; --i){ 464 | this.shiftLayer(layer.layers[i], shiftX, shiftY) 465 | } 466 | } 467 | 468 | DocUtils.doOutlineLayer = function(layer) { 469 | this.doOutlineItems(layer.pageItems); 470 | for(var i=0; ivisBounds[0]){ 522 | rect[0] = visBounds[0]; 523 | } 524 | if(rect[1]visBounds[3]){ 531 | rect[3] = visBounds[3]; 532 | } 533 | } 534 | } 535 | if(maskRect && rect){ 536 | if(rect[0]maskRect[1]){ 540 | rect[1] = maskRect[1]; 541 | } 542 | if(rect[2]>maskRect[2]){ 543 | rect[2] = maskRect[2]; 544 | } 545 | if(rect[3]