/* * Copyright (c) 2012, 2013 Hemanta Sapkota. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Hemanta Sapkota (laex.pearl@gmail.com) */ package com.laex.cg2d.entityeditor.ui; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.draw2d.FigureCanvas; import org.eclipse.draw2d.FreeformLayeredPane; import org.eclipse.draw2d.FreeformLayout; import org.eclipse.draw2d.ImageFigure; import org.eclipse.draw2d.RectangleFigure; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Spinner; import org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Section; import swing2swt.layout.BorderLayout; import com.laex.cg2d.model.ICGCProject; import com.laex.cg2d.model.adapter.RectAdapter; import com.laex.cg2d.model.model.EntitySpritesheetItem; import com.laex.cg2d.model.model.JsonSprite; import com.laex.cg2d.model.model.ResourceFile; import com.laex.cg2d.model.resources.ResourceManager; /** * The Class ImportSpritesComposite. */ public class ImportSpritesComposite extends Composite { /** The spritesheet image file. */ private ResourceFile spritesheetImageFile = ResourceFile.EMPTY; /** The spritesheet json mapper file. */ private ResourceFile spritesheetJsonMapperFile = ResourceFile.EMPTY; /** The selected image. */ private Image selectedImage; /** The flp. */ private FreeformLayeredPane flp = new FreeformLayeredPane(); /** The toolkit. */ private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); /** The txt rows. */ private Spinner txtRows; /** The txt tile width. */ private Spinner txtTileWidth; /** The spritesheet items. */ protected ArrayList<EntitySpritesheetItem> spritesheetItems = new ArrayList<EntitySpritesheetItem>(); /** The extracted images. */ private Queue<Image> extractedImages = new LinkedList<Image>(); /** The txt cols. */ private Spinner txtCols; /** The txt tile height. */ private Spinner txtTileHeight; /** The figure canvas. */ private FigureCanvas figureCanvas; /** The delegate. */ private ImportSpriteCompositeDelegate delegate; /** * The listener interface for receiving extractionDataModify events. * The class that is interested in processing a extractionDataModify * event implements this interface, and the object created * with that class is registered with a component using the * component's <code>addExtractionDataModifyListener<code> method. When * the extractionDataModify event occurs, that object's appropriate * method is invoked. * * @see ExtractionDataModifyEvent */ class ExtractionDataModifyListener implements ModifyListener { /* * (non-Javadoc) * * @see * org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events * .ModifyEvent) */ @Override public void modifyText(ModifyEvent e) { flp.removeAll(); setSelectedImageToCanvas(); updateOutline(); } } /** The edm. */ private ExtractionDataModifyListener edm = new ExtractionDataModifyListener(); /** The resource container. */ private IResource resourceContainer; /** The btn enable extract. */ private Button btnEnableExtract; /** The lbl count. */ private Label lblCount; /** * Sets the delegate. * * @param delegate the new delegate */ public void setDelegate(ImportSpriteCompositeDelegate delegate) { this.delegate = delegate; } /** * Sets the selected image to canvas. */ private void setSelectedImageToCanvas() { flp.removeAll(); selectedImage = ResourceManager.getImageOfRelativePath(spritesheetImageFile.getResourceFile()); ImageFigure iff = new ImageFigure(selectedImage); iff.setBounds(new Rectangle(0, 0, selectedImage.getBounds().width, selectedImage.getBounds().height)); flp.add(iff); figureCanvas.setBounds(0, 0, selectedImage.getBounds().width, selectedImage.getBounds().height); } /** * Update outline. */ private void updateOutline() { int cols = txtCols.getSelection(); int rows = txtRows.getSelection(); int imgWidth = selectedImage.getBounds().width; int imgHeight = selectedImage.getBounds().height; if (cols == 0) cols = 1; if (rows == 0) rows = 1; int tileWidth = imgWidth / cols; int tileHeight = imgHeight / rows; txtTileWidth.setSelection(tileWidth); txtTileHeight.setSelection(tileHeight); extractedImages.clear(); List<JsonSprite> lst = new ArrayList<JsonSprite>(); for (int y = 0; y < imgHeight; y += tileHeight) { for (int x = 0; x < imgWidth; x += tileWidth) { RectangleFigure rf = createBlockFigure(x, y, tileWidth, tileHeight); flp.add(rf); JsonSprite js = new JsonSprite("", x, y, tileWidth, tileHeight, 0, 0); lst.add(js); } } /* Only extract if selected by user */ if (btnEnableExtract.getSelection()) { extractFromJSON(lst); } figureCanvas.setContents(flp); } /** * Creates the block figure. * * @param x the x * @param y the y * @param tileWidth the tile width * @param tileHeight the tile height * @return the rectangle figure */ private RectangleFigure createBlockFigure(int x, int y, int tileWidth, int tileHeight) { RectangleFigure rf = new RectangleFigure(); rf.setAlpha(120); rf.setBounds(new Rectangle(x, y, tileWidth, tileHeight)); return rf; } /** * Gets the spritesheet items. * * @return the spritesheet items */ public ArrayList<EntitySpritesheetItem> getSpritesheetItems() { return spritesheetItems; } /** * Clear outline. */ private void clearOutline() { flp.removeAll(); figureCanvas.setContents(null); } /** * Open json file opener. * * @return the list */ protected List<JsonSprite> openJsonFileOpener() { List<JsonSprite> list = new ArrayList<JsonSprite>(); FilteredResourcesSelectionDialog frsd = openResourceLoader("*.json"); int resp = frsd.open(); if (resp == FilteredResourcesSelectionDialog.CANCEL) { return list; } IFile selectedFile = (IFile) frsd.getFirstResult(); String spritesheetJsonFile = selectedFile.getFullPath().toOSString(); String spritesheetJsonAbs = selectedFile.getLocation().makeAbsolute().toOSString(); spritesheetJsonMapperFile = ResourceFile.create(spritesheetJsonFile, spritesheetJsonAbs); // JsonReader jr = new JsonReader(); // try { // JsonValue json = jr.parse(selectedFile.getContents()); // // Entries entries = json.entries(); // // while (entries.hasNext()) { // Entry e = entries.next(); // // if (e.key.equals("image") || e.key.equals("spriteCount")) { // continue; // } // // OrderedMap sprite = (OrderedMap) e.value; // // String spriteName = (String) sprite.get("id"); // int x = (int) Float.parseFloat(sprite.get("x").toString()); // int y = (int) Float.parseFloat(sprite.get("y").toString()); // int width = (int) Float.parseFloat(sprite.get("width").toString()); // int height = (int) Float.parseFloat(sprite.get("height").toString()); // // JsonSprite js = new JsonSprite(spriteName, x, y, width, height, 0, 0); // list.add(js); // } // // } catch (CoreException e) { // Activator.log(e); // } return list; } /** * Extract from json. * * @param lst the lst */ private void extractFromJSON(final List<JsonSprite> lst) { spritesheetItems = new ArrayList<EntitySpritesheetItem>(); clearOutline(); setSelectedImageToCanvas(); ProgressMonitorDialog pmd = new ProgressMonitorDialog(getShell()); try { pmd.run(false, false, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { int index = 0; for (JsonSprite js : lst) { Rectangle r = new Rectangle(js.getX(), js.getY(), js.getWidth(), js.getHeight()); EntitySpritesheetItem esi = new EntitySpritesheetItem(); esi.setExtractBounds(RectAdapter.gdxRect(r)); esi.setFrameIndex(index++); spritesheetItems.add(esi); final RectangleFigure rf = createBlockFigure(r.x, r.y, r.width, r.height); flp.add(rf); final ImageData id = ResourceManager.extractImageFromBounds(selectedImage.getImageData(), RectAdapter.swtRect(rf.getBounds())); extractedImages.add(ResourceManager.getImage(id)); } lblCount.setText("#" + String.valueOf(extractedImages.size())); if (delegate != null) { delegate.spriteExtractionComplete(spritesheetImageFile, spritesheetJsonMapperFile, spritesheetItems, extractedImages); } } }); } catch (InvocationTargetException e1) { e1.printStackTrace(); } catch (InterruptedException e1) { e1.printStackTrace(); } figureCanvas.setContents(flp); } /** * Open resource loader. * * @param pattern the pattern * @return the filtered resources selection dialog */ private FilteredResourcesSelectionDialog openResourceLoader(String pattern) { IFolder texFlder = resourceContainer.getProject().getFolder(ICGCProject.TEXTURES_FOLDER); FilteredResourcesSelectionDialog frsd = new FilteredResourcesSelectionDialog(getShell(), false, texFlder, IResource.FILE); frsd.setTitle("Select a image. All the images have been listed from the textures folder"); frsd.setInitialPattern(pattern); return frsd; } /** * Choose image. */ protected void chooseImage() { FilteredResourcesSelectionDialog frsd = openResourceLoader("*.png"); int resp = frsd.open(); if (resp == FilteredResourcesSelectionDialog.CANCEL) { return; } IFile selectedFile = (IFile) frsd.getFirstResult(); String resourceFile = selectedFile.getFullPath().toOSString(); String resourceFileAbsolute = selectedFile.getLocation().makeAbsolute().toOSString(); spritesheetImageFile = ResourceFile.create(resourceFile, resourceFileAbsolute); // set the image to figure canvas setSelectedImageToCanvas(); updateOutline(); } /** * Toggle extract items. */ private void toggleExtractItems() { if (!btnEnableExtract.getSelection()) { txtRows.setEnabled(false); txtCols.setEnabled(false); txtTileHeight.setEnabled(false); txtTileWidth.setEnabled(false); } else { txtRows.setEnabled(true); txtCols.setEnabled(true); txtTileWidth.setEnabled(false); txtTileHeight.setEnabled(false); } } /** * Create the composite. * * @param parent the parent * @param style the style */ public ImportSpritesComposite(Composite parent, int style) { this(null, parent, style); } /** * Instantiates a new import sprites composite. * * @param container the container * @param parent the parent * @param style the style */ public ImportSpritesComposite(IResource container, Composite parent, int style) { super(parent, style); this.resourceContainer = container; addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { toolkit.dispose(); } }); toolkit.adapt(this); toolkit.paintBordersFor(this); setLayout(new FillLayout(SWT.HORIZONTAL)); Composite composite = toolkit.createComposite(this, SWT.NONE); toolkit.paintBordersFor(composite); composite.setLayout(new BorderLayout(0, 0)); Button btnChooseImage = toolkit.createButton(composite, "Choose Spritesheet", SWT.NONE); btnChooseImage.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { chooseImage(); } }); btnChooseImage.setLayoutData(BorderLayout.NORTH); Section sctnExtract = toolkit.createSection(composite, Section.EXPANDED | Section.TITLE_BAR); sctnExtract.setLayoutData(BorderLayout.WEST); toolkit.paintBordersFor(sctnExtract); sctnExtract.setText("Extract"); sctnExtract.setExpanded(true); Composite composite_1 = toolkit.createComposite(sctnExtract, SWT.NONE); toolkit.paintBordersFor(composite_1); sctnExtract.setClient(composite_1); composite_1.setLayout(new RowLayout(SWT.VERTICAL)); Label lblColumns = toolkit.createLabel(composite_1, "Columns", SWT.NONE); txtCols = new Spinner(composite_1, SWT.BORDER); txtCols.setSelection(8); txtCols.addModifyListener(edm); toolkit.adapt(txtCols); toolkit.paintBordersFor(txtCols); Label lblRows = toolkit.createLabel(composite_1, "Rows", SWT.NONE); txtRows = new Spinner(composite_1, SWT.BORDER); txtRows.setSelection(1); txtRows.addModifyListener(edm); Label lblWidth = new Label(composite_1, SWT.NONE); toolkit.adapt(lblWidth, true, true); lblWidth.setText("Tile Width"); txtTileWidth = new Spinner(composite_1, SWT.BORDER); txtTileWidth.setEnabled(false); // txtTileWidth.addModifyListener(edm); Label lblTileHeight = toolkit.createLabel(composite_1, "Tile Height", SWT.NONE); txtTileHeight = new Spinner(composite_1, SWT.BORDER); txtTileHeight.setEnabled(false); // txtTileHeight.addModifyListener(edm); toolkit.adapt(txtTileHeight); toolkit.paintBordersFor(txtTileHeight); Label label = toolkit.createSeparator(composite_1, SWT.HORIZONTAL); Button btnJSON = toolkit.createButton(composite_1, "JSON", SWT.NONE); Label label_1 = toolkit.createSeparator(composite_1, SWT.HORIZONTAL); lblCount = toolkit.createLabel(composite_1, "#", SWT.NONE); btnEnableExtract = new Button(sctnExtract, SWT.CHECK); btnEnableExtract.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { toggleExtractItems(); } }); toolkit.adapt(btnEnableExtract, true, true); btnEnableExtract.setBackground(null); sctnExtract.setTextClient(btnEnableExtract); btnJSON.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { final List<JsonSprite> lst = openJsonFileOpener(); extractFromJSON(lst); } }); ScrolledComposite spriteComposite = new ScrolledComposite(composite, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); spriteComposite.setLayoutData(BorderLayout.CENTER); toolkit.adapt(spriteComposite); toolkit.paintBordersFor(spriteComposite); spriteComposite.setExpandHorizontal(true); spriteComposite.setExpandVertical(true); flp.setLayoutManager(new FreeformLayout()); toolkit.adapt(spriteComposite); toolkit.paintBordersFor(spriteComposite); figureCanvas = new FigureCanvas(spriteComposite); flp.setLayoutManager(new FreeformLayout()); toolkit.adapt(figureCanvas); toolkit.paintBordersFor(figureCanvas); spriteComposite.setContent(figureCanvas); spriteComposite.setMinSize(figureCanvas.computeSize(SWT.DEFAULT, SWT.DEFAULT)); toggleExtractItems(); } }