/* * ****************************************************************************** * * Copyright 2015 See AUTHORS file. * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * ***************************************************************************** */ package com.uwsoft.editor.proxy; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.tools.texturepacker.TexturePacker; import com.badlogic.gdx.tools.texturepacker.TexturePacker.Settings; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Json; import com.google.common.collect.Lists; import com.kotcrab.vis.ui.util.dialog.DialogUtils; import com.puremvc.patterns.proxy.BaseProxy; import com.uwsoft.editor.Overlap2DFacade; import com.uwsoft.editor.data.manager.PreferencesManager; import com.uwsoft.editor.data.migrations.ProjectVersionMigrator; import com.uwsoft.editor.renderer.data.*; import com.uwsoft.editor.renderer.utils.MySkin; import com.uwsoft.editor.utils.AppConfig; import com.uwsoft.editor.utils.Overlap2DUtils; import com.uwsoft.editor.view.menu.Overlap2DMenuBar; import com.uwsoft.editor.view.stage.Sandbox; import com.uwsoft.editor.view.ui.widget.ProgressHandler; import com.vo.EditorConfigVO; import com.vo.ProjectVO; import com.vo.SceneConfigVO; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.imageio.ImageIO; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.awt.image.BufferedImage; import java.io.*; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ProjectManager extends BaseProxy { private static final String TAG = ProjectManager.class.getCanonicalName(); public static final String NAME = TAG; private static final String EVENT_PREFIX = "com.uwsoft.editor.proxy.ProjectManager"; public static final String PROJECT_OPENED = EVENT_PREFIX + ".PROJECT_OPENED"; public static final String PROJECT_DATA_UPDATED = EVENT_PREFIX + ".PROJECT_DATA_UPDATED"; private static final String IMAGE_DIR_PATH = "assets/orig/images"; private static final String SPINE_DIR_PATH = "assets/orig/spine-animations"; private static final String SPRITE_DIR_PATH = "assets/orig/sprite-animations"; private static final String SPRITER_DIR_PATH = "assets/orig/animations"; private static final String PARTICLE_DIR_PATH = "assets/orig/particles"; public ProjectVO currentProjectVO; public ProjectInfoVO currentProjectInfoVO; private String currentProjectPath; private String defaultWorkspacePath; private String DEFAULT_FOLDER = "Overlap2D"; private float currentPercent = 0.0f; private ProgressHandler handler; private EditorConfigVO editorConfigVO; public ProjectManager() { super(NAME); } @Override public void onRegister() { super.onRegister(); facade = Overlap2DFacade.getInstance(); initWorkspace(); } @Override public void onRemove() { super.onRemove(); } public ProjectVO getCurrentProjectVO() { return currentProjectVO; } public ProjectInfoVO getCurrentProjectInfoVO() { return currentProjectInfoVO; } private void initWorkspace() { try { editorConfigVO = getEditorConfig(); String myDocPath = Overlap2DUtils.MY_DOCUMENTS_PATH; defaultWorkspacePath = myDocPath + File.separator + DEFAULT_FOLDER; FileUtils.forceMkdir(new File(defaultWorkspacePath)); } catch (IOException e) { e.printStackTrace(); } } private void changePercentBy(float value) { currentPercent += value; handler.progressChanged(currentPercent); } public void createEmptyProject(String projectPath, int width, int height, int pixelPerWorldUnit) throws IOException { /* if (workspacePath.endsWith(File.separator)) { workspacePath = workspacePath.substring(0, workspacePath.length() - 1); } String projPath = workspacePath + File.separator + projectName; */ String projectName = new File(projectPath).getName(); String projPath = FilenameUtils.normalize(projectPath); FileUtils.forceMkdir(new File(projPath)); FileUtils.forceMkdir(new File(projPath + File.separator + "export")); FileUtils.forceMkdir(new File(projPath + File.separator + "assets")); FileUtils.forceMkdir(new File(projPath + File.separator + "scenes")); FileUtils.forceMkdir(new File(projPath + File.separator + "assets/orig")); FileUtils.forceMkdir(new File(projPath + File.separator + "assets/orig/images")); FileUtils.forceMkdir(new File(projPath + File.separator + "assets/orig/particles")); FileUtils.forceMkdir(new File(projPath + File.separator + "assets/orig/animations")); FileUtils.forceMkdir(new File(projPath + File.separator + "assets/orig/pack")); // create project file ProjectVO projVo = new ProjectVO(); projVo.projectName = projectName; projVo.projectVersion = ProjectVersionMigrator.dataFormatVersion; // create project info file ProjectInfoVO projInfoVo = new ProjectInfoVO(); projInfoVo.originalResolution.name = "orig"; projInfoVo.originalResolution.width = width; projInfoVo.originalResolution.height = height; projInfoVo.pixelToWorld = pixelPerWorldUnit; //TODO: add project orig resolution setting currentProjectVO = projVo; currentProjectInfoVO = projInfoVo; currentProjectPath = projPath; SceneDataManager sceneDataManager = facade.retrieveProxy(SceneDataManager.NAME); sceneDataManager.createNewScene("MainScene"); FileUtils.writeStringToFile(new File(projPath + "/project.pit"), projVo.constructJsonString(), "utf-8"); FileUtils.writeStringToFile(new File(projPath + "/project.dt"), projInfoVo.constructJsonString(), "utf-8"); } public void setLastOpenedPath(String path) { editorConfigVO.lastOpenedSystemPath = path; saveEditorConfig(); } private void saveEditorConfig() { try { File root = new File(new File(".").getAbsolutePath()).getParentFile(); String configFilePath = root.getAbsolutePath() + "/" + EditorConfigVO.EDITOR_CONFIG_FILE; FileUtils.writeStringToFile(new File(configFilePath), editorConfigVO.constructJsonString(), "utf-8"); } catch (IOException e) { e.printStackTrace(); } } public void openProjectAndLoadAllData(String projectPath) { openProjectAndLoadAllData(projectPath, null); } public void openProjectAndLoadAllData(String projectPath, String resolution) { String prjFilePath = projectPath + "/project.pit"; PreferencesManager prefs = PreferencesManager.getInstance(); prefs.buildRecentHistory(); prefs.pushHistory(prjFilePath); facade.sendNotification(Overlap2DMenuBar.RECENT_LIST_MODIFIED); File prjFile = new File(prjFilePath); if (prjFile.exists() && !prjFile.isDirectory()) { FileHandle projectFile = Gdx.files.internal(prjFilePath); String projectContents = null; try { projectContents = FileUtils.readFileToString(projectFile.file()); Json json = new Json(); json.setIgnoreUnknownFields(true); ProjectVO vo = json.fromJson(ProjectVO.class, projectContents); goThroughVersionMigrationProtocol(projectPath, vo); currentProjectVO = vo; String prjInfoFilePath = projectPath + "/project.dt"; FileHandle projectInfoFile = Gdx.files.internal(prjInfoFilePath); String projectInfoContents = FileUtils.readFileToString(projectInfoFile.file()); ProjectInfoVO voInfo = json.fromJson(ProjectInfoVO.class, projectInfoContents); currentProjectInfoVO = voInfo; } catch (IOException e) { e.printStackTrace(); } ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); if (resolution == null) { resolutionManager.currentResolutionName = currentProjectVO.lastOpenResolution.isEmpty() ? "orig" : currentProjectVO.lastOpenResolution; } else { resolutionManager.currentResolutionName = resolution; currentProjectVO.lastOpenResolution = resolutionManager.currentResolutionName; saveCurrentProject(); } currentProjectPath = projectPath; checkForConsistency(projectPath); loadProjectData(projectPath); } } private void goThroughVersionMigrationProtocol(String projectPath, ProjectVO projectVo) { ProjectVersionMigrator pvm = new ProjectVersionMigrator(projectPath, projectVo); pvm.start(); } private void checkForConsistency(String projectPath) { // check if current project requires cleanup FileHandle sourceDir = new FileHandle(projectPath + "/scenes/"); for (FileHandle entry : sourceDir.list(Overlap2DUtils.DT_FILTER)) { if (!entry.file().isDirectory()) { Json json = new Json(); json.setIgnoreUnknownFields(true); SceneVO sceneVO = json.fromJson(SceneVO.class, entry); if (sceneVO.composite == null) continue; ArrayList<MainItemVO> items = sceneVO.composite.getAllItems(); for (CompositeItemVO libraryItem : currentProjectInfoVO.libraryItems.values()) { if (libraryItem.composite == null) continue; items = libraryItem.composite.getAllItems(); } } } } public void reLoadProjectAssets() { ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); ResourceManager resourceManager = facade.retrieveProxy(ResourceManager.NAME); resourceManager.loadCurrentProjectAssets(currentProjectPath + "/assets/" + resolutionManager.currentResolutionName + "/pack/pack.atlas"); } public void loadProjectData(String projectPath) { // All legit loading assets ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); ResourceManager resourceManager = facade.retrieveProxy(ResourceManager.NAME); resourceManager.loadCurrentProjectData(projectPath, resolutionManager.currentResolutionName); } public void saveCurrentProject() { try { FileUtils.writeStringToFile(new File(currentProjectPath + "/project.pit"), currentProjectVO.constructJsonString(), "utf-8"); FileUtils.writeStringToFile(new File(currentProjectPath + "/project.dt"), currentProjectInfoVO.constructJsonString(), "utf-8"); } catch (IOException e) { e.printStackTrace(); } } public void saveCurrentProject(SceneVO vo) { saveCurrentProject(); SceneDataManager sceneDataManager = facade.retrieveProxy(SceneDataManager.NAME); sceneDataManager.saveScene(vo); } private ArrayList<File> getScmlFileImagesList(FileHandle fileHandle) { ArrayList<File> images = new ArrayList<File>(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = null; try { db = dbf.newDocumentBuilder(); org.w3c.dom.Document document = db.parse(fileHandle.file()); NodeList nodeList = document.getElementsByTagName("file"); for (int x = 0, size = nodeList.getLength(); x < size; x++) { String absolutePath = fileHandle.path(); String path = absolutePath.substring(0, FilenameUtils.indexOfLastSeparator(fileHandle.path())) + File.separator + nodeList.item(x).getAttributes().getNamedItem("name").getNodeValue(); File imgFile = new File(path); images.add(imgFile); } } catch (SAXException | IOException | ParserConfigurationException e) { e.printStackTrace(); } return images; } public void importSpineAnimationsIntoProject(final Array<FileHandle> fileHandles, ProgressHandler progressHandler) { if (fileHandles == null) { return; } handler = progressHandler; currentPercent = 0; ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(() -> { for (FileHandle handle : fileHandles) { File copiedFile = importExternalAnimationIntoProject(handle); if (copiedFile.getName().toLowerCase().endsWith(".atlas")) { ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); resolutionManager.resizeSpineAnimationForAllResolutions(copiedFile, currentProjectInfoVO); } else if (copiedFile.getName().toLowerCase().endsWith(".scml")) { //resizeSpriterAnimationForAllResolutions(copiedFile, currentProjectInfoVO); } } }); executor.execute(() -> { changePercentBy(100 - currentPercent); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } handler.progressComplete(); }); executor.shutdown(); } public File importExternalAnimationIntoProject(FileHandle animationFileSource) { try { String fileName = animationFileSource.name(); if (!Overlap2DUtils.JSON_FILTER.accept(null, fileName) && !Overlap2DUtils.SCML_FILTER.accept(null, fileName)) { //showError("Spine animation should be a .json file with atlas in same folder \n Spriter animation should be a .scml file with images in same folder"); return null; } String fileNameWithOutExt = FilenameUtils.removeExtension(fileName); String sourcePath; String animationDataPath; String targetPath; if (Overlap2DUtils.JSON_FILTER.accept(null, fileName)) { sourcePath = animationFileSource.path(); animationDataPath = FilenameUtils.getFullPathNoEndSeparator(sourcePath); targetPath = currentProjectPath + "/assets/orig/spine-animations" + File.separator + fileNameWithOutExt; FileHandle atlasFileSource = new FileHandle(animationDataPath + File.separator + fileNameWithOutExt + ".atlas"); if (!atlasFileSource.exists()) { //showError("the atlas file needs to have same name and location as the json file"); return null; } FileUtils.forceMkdir(new File(targetPath)); File jsonFileTarget = new File(targetPath + File.separator + fileNameWithOutExt + ".json"); File atlasFileTarget = new File(targetPath + File.separator + fileNameWithOutExt + ".atlas"); Array<File> imageFiles = getAtlasPages(atlasFileSource); FileUtils.copyFile(animationFileSource.file(), jsonFileTarget); FileUtils.copyFile(atlasFileSource.file(), atlasFileTarget); for (File imageFile : imageFiles) { FileHandle imgFileTarget = new FileHandle(targetPath + File.separator + imageFile.getName()); FileUtils.copyFile(imageFile, imgFileTarget.file()); } return atlasFileTarget; } else if (Overlap2DUtils.SCML_FILTER.accept(null, fileName)) { targetPath = currentProjectPath + "/assets/orig/spriter-animations" + File.separator + fileNameWithOutExt; File scmlFileTarget = new File(targetPath + File.separator + fileNameWithOutExt + ".scml"); ArrayList<File> imageFiles = getScmlFileImagesList(animationFileSource); FileUtils.copyFile(animationFileSource.file(), scmlFileTarget); for (File imageFile : imageFiles) { File imgFileTarget = new File(targetPath + File.separator + imageFile.getName()); FileUtils.copyFile(imageFile, imgFileTarget); } return scmlFileTarget; } } catch (IOException e) { e.printStackTrace(); } return null; } public void importSpriteAnimationsIntoProject(final Array<FileHandle> fileHandles, ProgressHandler progressHandler) { if (fileHandles == null) { return; } handler = progressHandler; ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(() -> { String newAnimName = null; String rawFileName = fileHandles.get(0).name(); String fileExtension = FilenameUtils.getExtension(rawFileName); if (fileExtension.equals("png")) { Settings settings = new Settings(); settings.square = true; settings.flattenPaths = true; TexturePacker texturePacker = new TexturePacker(settings); String fileNameWithoutExt = FilenameUtils.removeExtension(rawFileName); String fileNameWithoutFrame = fileNameWithoutExt.replaceAll("\\d*$", ""); boolean noFileNameWithoutFrame = false; if (Objects.equals(fileNameWithoutFrame, "")) { fileNameWithoutFrame = fileHandles.get(0).parent().name(); noFileNameWithoutFrame = true; } String targetPath = currentProjectPath + "/assets/orig/sprite-animations" + File.separator + fileNameWithoutFrame; for (FileHandle file : fileHandles) { File src = file.file(); String destName; if (noFileNameWithoutFrame) { destName = targetPath + File.separator + fileNameWithoutFrame + src.getName(); } else { destName = targetPath + File.separator + src.getName(); } File dest = new File(destName); try { FileUtils.copyFile(src, dest); } catch (IOException e) { e.printStackTrace(); } } FileHandle pngsDir = new FileHandle(targetPath); for (FileHandle entry : pngsDir.list(Overlap2DUtils.PNG_FILTER)) { texturePacker.addImage(entry.file()); } String packName = "Pack"; targetPath = targetPath + packName; File targetDir = new File(targetPath); if (targetDir.exists()) { try { FileUtils.deleteDirectory(targetDir); } catch (IOException e) { e.printStackTrace(); } } texturePacker.pack(targetDir, fileNameWithoutFrame + packName); //delete newly created directory and images try { FileUtils.deleteDirectory(pngsDir.file()); } catch (IOException e) { e.printStackTrace(); } newAnimName = fileNameWithoutFrame + packName; } else { for (FileHandle fileHandle : fileHandles) { try { Array<File> imgs = getAtlasPages(fileHandle); String fileNameWithoutExt = FilenameUtils.removeExtension(fileHandle.name()); String targetPath = currentProjectPath + "/assets/orig/sprite-animations" + File.separator + fileNameWithoutExt; File targetDir = new File(targetPath); if (targetDir.exists()) { FileUtils.deleteDirectory(targetDir); } for (File img : imgs) { FileUtils.copyFileToDirectory(img, targetDir); } FileUtils.copyFileToDirectory(fileHandle.file(), targetDir); newAnimName = fileNameWithoutExt; } catch (IOException e) { e.printStackTrace(); } } } if (newAnimName != null) { ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); resolutionManager.resizeSpriteAnimationForAllResolutions(newAnimName, currentProjectInfoVO); } }); executor.execute(() -> { changePercentBy(100 - currentPercent); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } handler.progressComplete(); }); executor.shutdown(); } private Array<File> getAtlasPages(FileHandle fileHandle) { Array<File> imgs = new Array<>(); try { BufferedReader reader = new BufferedReader(new InputStreamReader(fileHandle.read()), 64); while (true) { String line = reader.readLine(); if (line == null) break; if (line.trim().length() == 0) { line = reader.readLine(); imgs.add(new File(FilenameUtils.getFullPath(fileHandle.path()) + line)); } } } catch (IOException e) { e.printStackTrace(); } return imgs; } private Array<FileHandle> getAtlasPageHandles(FileHandle fileHandle) { Array<File> imgs = getAtlasPages(fileHandle); Array<FileHandle> imgHandles = new Array<>(); for (int i = 0; i < imgs.size; i++) { imgHandles.add(new FileHandle(imgs.get(i))); } return imgHandles; } private boolean addParticleEffectImages(FileHandle fileHandle, Array<FileHandle> imgs) { try { BufferedReader reader = new BufferedReader(new InputStreamReader(fileHandle.read()), 64); while (true) { String line = reader.readLine(); if (line == null) break; if (line.trim().equals("- Image Path -")) { line = reader.readLine(); if (line.contains("\\") || line.contains("/")) { // then it's a path let's see if exists. File tmp = new File(line); if (tmp.exists()) { imgs.add(new FileHandle(tmp)); } else { line = FilenameUtils.getBaseName(line) + ".png"; File file = new File(FilenameUtils.getFullPath(fileHandle.path()) + line); if (file.exists()) { imgs.add(new FileHandle(file)); } else { return false; } } } else { File file = new File(FilenameUtils.getFullPath(fileHandle.path()) + line); if (file.exists()) { imgs.add(new FileHandle(file)); } else { return false; } } } } } catch (IOException e) { e.printStackTrace(); } return true; } public void importParticlesIntoProject(final Array<FileHandle> fileHandles, ProgressHandler progressHandler) { if (fileHandles == null) { return; } final String targetPath = currentProjectPath + "/assets/orig/particles"; handler = progressHandler; currentPercent = 0; ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(() -> { Array<FileHandle> imgs = new Array<>(); for (FileHandle fileHandle : fileHandles) { if (!fileHandle.isDirectory() && fileHandle.exists()) { try { //copy images boolean allImagesFound = addParticleEffectImages(fileHandle, imgs); if (allImagesFound) { // copy the fileHandle String newName = fileHandle.name(); File target = new File(targetPath + "/" + newName); FileUtils.copyFile(fileHandle.file(), target); } } catch (Exception e) { //e.printStackTrace(); //System.out.println("Error importing particles"); //showError("Error importing particles \n Particle Atals not found \n Please place particle atlas and particle effect fileHandle in the same directory "); } } } if (imgs.size > 0) { copyImageFilesForAllResolutionsIntoProject(imgs, false); } ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); resolutionManager.rePackProjectImagesForAllResolutions(); }); executor.execute(() -> { changePercentBy(100 - currentPercent); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } handler.progressComplete(); }); executor.shutdown(); } public void importAtlasesIntoProject(final Array<FileHandle> files, ProgressHandler progressHandler) { handler = progressHandler; currentPercent = 0; ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(() -> { for (FileHandle fileHandle : files) { // TODO: logic goes here } }); executor.execute(() -> { changePercentBy(100 - currentPercent); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } handler.progressComplete(); }); executor.shutdown(); } public void importImagesIntoProject(final Array<FileHandle> files, ProgressHandler progressHandler) { if (files == null) { return; } handler = progressHandler; currentPercent = 0; ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(() -> { copyImageFilesForAllResolutionsIntoProject(files, true); ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); resolutionManager.rePackProjectImagesForAllResolutions(); }); executor.execute(() -> { changePercentBy(100 - currentPercent); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } handler.progressComplete(); }); executor.shutdown(); } private void copyImageFilesForAllResolutionsIntoProject(Array<FileHandle> files, Boolean performResize) { copyImageFilesIntoProject(files, currentProjectInfoVO.originalResolution, performResize); int totalWarnings = 0; for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) { totalWarnings += copyImageFilesIntoProject(files, resolutionEntryVO, performResize); } if (totalWarnings > 0) { DialogUtils.showOKDialog(Sandbox.getInstance().getUIStage(), "Warning", totalWarnings + " images were not resized for smaller resolutions due to already small size ( < 3px )"); } } /** * @param files * @param resolution * @param performResize * @return number of images that did needed to be resized but failed */ private int copyImageFilesIntoProject(Array<FileHandle> files, ResolutionEntryVO resolution, Boolean performResize) { float ratio = ResolutionManager.getResolutionRatio(resolution, currentProjectInfoVO.originalResolution); String targetPath = currentProjectPath + "/assets/" + resolution.name + "/images"; float perCopyPercent = 95.0f / files.size; int resizeWarningsCount = 0; for (FileHandle handle : files) { if (!Overlap2DUtils.PNG_FILTER.accept(null, handle.name())) { continue; } try { BufferedImage bufferedImage; if (performResize) { bufferedImage = ResolutionManager.imageResize(handle.file(), ratio); if (bufferedImage == null) { bufferedImage = ImageIO.read(handle.file()); resizeWarningsCount++; } } else { bufferedImage = ImageIO.read(handle.file()); } File target = new File(targetPath); if (!target.exists()) { File newFile = new File(targetPath); newFile.mkdir(); } ImageIO.write(bufferedImage, "png", new File(targetPath + "/" + handle.name().replace("_", ""))); } catch (IOException e) { e.printStackTrace(); } changePercentBy(perCopyPercent); } return resizeWarningsCount; } public void importFontIntoProject(Array<FileHandle> fileHandles, ProgressHandler progressHandler) { if (fileHandles == null) { return; } String targetPath = currentProjectPath + "/assets/orig/freetypefonts"; handler = progressHandler; float perCopyPercent = 95.0f / fileHandles.size; for (FileHandle fileHandle : fileHandles) { if (!Overlap2DUtils.TTF_FILTER.accept(null, fileHandle.name())) { continue; } try { File target = new File(targetPath); if (!target.exists()) { File newFile = new File(targetPath); newFile.mkdir(); } File fileTarget = new File(targetPath + "/" + fileHandle.name()); FileUtils.copyFile(fileHandle.file(), fileTarget); } catch (IOException e) { e.printStackTrace(); } System.out.println(perCopyPercent); changePercentBy(perCopyPercent); ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(() -> { changePercentBy(100 - currentPercent); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } handler.progressComplete(); }); executor.shutdown(); } } public void importStyleIntoProject(final FileHandle handle, ProgressHandler progressHandler) { if (handle == null) { return; } final String targetPath = currentProjectPath + "/assets/orig/styles"; FileHandle fileHandle = Gdx.files.absolute(handle.path()); final MySkin skin = new MySkin(fileHandle); handler = progressHandler; currentPercent = 0; ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(() -> { for (int i = 0; i < skin.fontFiles.size(); i++) { File copyFontFile = new File(handle.path(), skin.fontFiles.get(i) + ".fnt"); File copyImageFile = new File(handle.path(), skin.fontFiles.get(i) + ".png"); if (!handle.isDirectory() && handle.exists() && copyFontFile.isFile() && copyFontFile.exists() && copyImageFile.isFile() && copyImageFile.exists()) { File fileTarget = new File(targetPath + "/" + handle.name()); File fontTarget = new File(targetPath + "/" + copyFontFile.getName()); File imageTarget = new File(targetPath + "/" + copyImageFile.getName()); try { FileUtils.copyFile(handle.file(), fileTarget); FileUtils.copyFile(copyFontFile, fontTarget); FileUtils.copyFile(copyImageFile, imageTarget); } catch (IOException e) { // TODO Auto-generated catch block System.err.println(e.getMessage()); e.printStackTrace(); } } else { System.err.println("SOME FILES ARE MISSING"); } } }); executor.execute(new Runnable() { @Override public void run() { changePercentBy(100 - currentPercent); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } handler.progressComplete(); } }); executor.shutdown(); } /** * @depricated */ public void copyDefaultStyleIntoProject() { /* String targetPath = currentWorkingPath + "/" + currentProjectVO.projectName + "/assets/orig/styles"; ResourceManager textureManager = facade.retrieveProxy(ResourceManager.NAME); File source = new File("assets/ui"); if (!(source.exists() && source.isDirectory())) { try { JarUtils.copyResourcesToDirectory(JarUtils.getThisJar(getClass()), "ui", targetPath); textureManager.loadCurrentProjectSkin(targetPath); return; } catch (Exception e) { e.printStackTrace(); } } File fileTarget = new File(targetPath); try { FileUtils.copyDirectory(source, fileTarget); textureManager.loadCurrentProjectSkin(targetPath); } catch (IOException e) { // TODO Auto-generated catch block System.err.println(e.getMessage()); e.printStackTrace(); } */ } public String getFreeTypeFontPath() { return currentProjectPath + "/assets/orig/freetypefonts"; } public void exportProject() { String defaultBuildPath = currentProjectPath + "/export"; exportPacks(defaultBuildPath); if (!currentProjectVO.projectMainExportPath.isEmpty()) { exportPacks(currentProjectVO.projectMainExportPath); } exportAnimations(defaultBuildPath); if (!currentProjectVO.projectMainExportPath.isEmpty()) { exportAnimations(currentProjectVO.projectMainExportPath); } exportParticles(defaultBuildPath); if (!currentProjectVO.projectMainExportPath.isEmpty()) { exportParticles(currentProjectVO.projectMainExportPath); } exportShaders(defaultBuildPath); if (!currentProjectVO.projectMainExportPath.isEmpty()) { exportShaders(currentProjectVO.projectMainExportPath); } exportFonts(defaultBuildPath); if (!currentProjectVO.projectMainExportPath.isEmpty()) { exportFonts(currentProjectVO.projectMainExportPath); } exportStyles(defaultBuildPath); SceneDataManager sceneDataManager = facade.retrieveProxy(SceneDataManager.NAME); sceneDataManager.buildScenes(defaultBuildPath); if (!currentProjectVO.projectMainExportPath.isEmpty()) { sceneDataManager.buildScenes(currentProjectVO.projectMainExportPath); } } private void exportStyles(String targetPath) { String srcPath = currentProjectPath + "/assets/orig"; FileHandle origDirectoryHandle = Gdx.files.absolute(srcPath); FileHandle stylesDirectory = origDirectoryHandle.child("styles"); File fileTarget = new File(targetPath + "/" + stylesDirectory.name()); try { FileUtils.copyDirectory(stylesDirectory.file(), fileTarget); } catch (IOException e) { //e.printStackTrace(); } } private void exportShaders(String targetPath) { String srcPath = currentProjectPath + "/assets"; FileHandle origDirectoryHandle = Gdx.files.absolute(srcPath); FileHandle shadersDirectory = origDirectoryHandle.child("shaders"); File fileTarget = new File(targetPath + "/" + shadersDirectory.name()); try { FileUtils.copyDirectory(shadersDirectory.file(), fileTarget); } catch (IOException e) { e.printStackTrace(); } } private void exportParticles(String targetPath) { String srcPath = currentProjectPath + "/assets/orig"; FileHandle origDirectoryHandle = Gdx.files.absolute(srcPath); FileHandle particlesDirectory = origDirectoryHandle.child("particles"); File fileTarget = new File(targetPath + "/" + particlesDirectory.name()); try { FileUtils.copyDirectory(particlesDirectory.file(), fileTarget); } catch (IOException e) { e.printStackTrace(); } } private void exportFonts(String targetPath) { String srcPath = currentProjectPath + "/assets/orig"; FileHandle origDirectoryHandle = Gdx.files.absolute(srcPath); FileHandle fontsDirectory = origDirectoryHandle.child("freetypefonts"); File fileTarget = new File(targetPath + "/" + fontsDirectory.name()); try { FileUtils.copyDirectory(fontsDirectory.file(), fileTarget); } catch (IOException e) { //e.printStackTrace(); } } private void exportAnimations(String targetPath) { exportSpineAnimationForResolution("orig", targetPath); exportSpriteAnimationForResolution("orig", targetPath); exportSpriterAnimationForResolution("orig", targetPath); for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) { exportSpineAnimationForResolution(resolutionEntryVO.name, targetPath); exportSpriteAnimationForResolution(resolutionEntryVO.name, targetPath); exportSpriterAnimationForResolution(resolutionEntryVO.name, targetPath); } } private void exportSpineAnimationForResolution(String res, String targetPath) { String spineSrcPath = currentProjectPath + "/assets/" + res + File.separator + "spine-animations"; try { FileUtils.forceMkdir(new File(targetPath + File.separator + res + File.separator + "spine_animations")); File fileSrc = new File(spineSrcPath); String finalTarget = targetPath + File.separator + res + File.separator + "spine_animations"; File fileTargetSpine = new File(finalTarget); FileUtils.copyDirectory(fileSrc, fileTargetSpine); } catch (IOException e) { //e.printStackTrace(); } } private void exportSpriteAnimationForResolution(String res, String targetPath) { String spineSrcPath = currentProjectPath + "/assets/" + res + File.separator + "sprite-animations"; try { FileUtils.forceMkdir(new File(targetPath + File.separator + res + File.separator + "sprite_animations")); File fileSrc = new File(spineSrcPath); String finalTarget = targetPath + File.separator + res + File.separator + "sprite_animations"; File fileTargetSprite = new File(finalTarget); FileUtils.copyDirectory(fileSrc, fileTargetSprite); } catch (IOException e) { //e.printStackTrace(); } } private void exportSpriterAnimationForResolution(String res, String targetPath) { String spineSrcPath = currentProjectPath + "/assets/" + res + File.separator + "spriter-animations"; try { FileUtils.forceMkdir(new File(targetPath + File.separator + res + File.separator + "spriter_animations")); File fileSrc = new File(spineSrcPath); String finalTarget = targetPath + File.separator + res + File.separator + "spriter_animations"; File fileTargetSpriter = new File(finalTarget); FileUtils.copyDirectory(fileSrc, fileTargetSpriter); } catch (IOException e) { //e.printStackTrace(); } } private void exportPacks(String targetPath) { String srcPath = currentProjectPath + "/assets"; FileHandle assetDirectoryHandle = Gdx.files.absolute(srcPath); FileHandle[] assetDirectories = assetDirectoryHandle.list(); for (FileHandle assetDirectory : assetDirectories) { if (assetDirectory.isDirectory()) { FileHandle assetDirectoryFileHandle = Gdx.files.absolute(assetDirectory.path()); FileHandle[] packFiles = assetDirectoryFileHandle.child("pack").list(); for (FileHandle packFile : packFiles) { File fileTarget = new File(targetPath + "/" + assetDirectory.name() + "/" + packFile.name()); try { FileUtils.copyFile(packFile.file(), fileTarget); } catch (IOException e) { e.printStackTrace(); } } } } } public void setExportPaths(String path) { currentProjectVO.projectMainExportPath = path; } public void setTexturePackerSizes(int width, int height) { currentProjectVO.texturepackerWidth = String.valueOf(width); currentProjectVO.texturepackerHeight = String.valueOf(height); } public void setTexturePackerDuplicate(boolean duplicate) { currentProjectVO.texturepackerDuplicate = duplicate; } public String getRootPath() { File root = new File(new File(".").getAbsolutePath()).getParentFile(); return root.getAbsolutePath(); } private EditorConfigVO getEditorConfig() { EditorConfigVO editorConfig = new EditorConfigVO(); String configFilePath = getRootPath() + "/" + EditorConfigVO.EDITOR_CONFIG_FILE; File configFile = new File(configFilePath); if (!configFile.exists()) { try { FileUtils.writeStringToFile(new File(configFilePath), editorConfig.constructJsonString(), "utf-8"); } catch (IOException e) { e.printStackTrace(); } } else { Json gson = new Json(); String editorConfigJson = null; try { editorConfigJson = FileUtils.readFileToString(Gdx.files.absolute(configFilePath).file()); editorConfig = gson.fromJson(EditorConfigVO.class, editorConfigJson); } catch (IOException e) { e.printStackTrace(); } } return editorConfig; } public void createNewProject(String projectPath, int originWidth, int originHeight, int pixelPerWorldUnit) { if (projectPath == null || projectPath.equals("")) { return; } String projectName = new File(projectPath).getName(); if (projectName.equals("")) { return; } try { createEmptyProject(projectPath, originWidth, originHeight, pixelPerWorldUnit); openProjectAndLoadAllData(projectPath); String workSpacePath = projectPath.substring(0, projectPath.lastIndexOf(projectName)); if (workSpacePath.length() > 0) { setLastOpenedPath(workSpacePath); } Sandbox.getInstance().loadCurrentProject(); facade.sendNotification(PROJECT_OPENED); //Set title with opened file path Gdx.graphics.setTitle(getFormatedTitle(projectPath)); } catch (IOException e) { e.printStackTrace(); } } public void openProjectFromPath(String path) { File projectFile = new File(path); File projectFolder = projectFile.getParentFile(); String projectName = projectFolder.getName(); editorConfigVO.lastOpenedSystemPath = projectFolder.getParentFile().getPath(); saveEditorConfig(); // here we load all data openProjectAndLoadAllData(projectFolder.getPath()); Sandbox.getInstance().loadCurrentProject(); facade.sendNotification(ProjectManager.PROJECT_OPENED); //Set title with opened file path Gdx.graphics.setTitle(getFormatedTitle(path)); } private String getFormatedTitle(String path) { //App Name + Version + path to opened file return "Overlap2D - Public Aplha v" + AppConfig.getInstance().version + " - [ " + path + " ]"; } public SceneConfigVO getCurrentSceneConfigVO() { for (int i = 0; i < currentProjectVO.sceneConfigs.size(); i++) { if (currentProjectVO.sceneConfigs.get(i).sceneName.equals(Sandbox.getInstance().getSceneControl().getCurrentSceneVO().sceneName)) { return currentProjectVO.sceneConfigs.get(i); } } SceneConfigVO newConfig = new SceneConfigVO(); newConfig.sceneName = Sandbox.getInstance().getSceneControl().getCurrentSceneVO().sceneName; currentProjectVO.sceneConfigs.add(newConfig); return newConfig; } public void importShaderIntoProject(Array<FileHandle> files, ProgressHandler progressHandler) { if (files == null) { return; } handler = progressHandler; currentPercent = 0; ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(() -> { for (FileHandle handle : files) { // check if shaders folder exists String shadersPath = currentProjectPath + "/assets/shaders"; File destination = new File(currentProjectPath + "/assets/shaders/" + handle.name()); try { FileUtils.forceMkdir(new File(shadersPath)); FileUtils.copyFile(handle.file(), destination); } catch (IOException e) { e.printStackTrace(); } } }); executor.execute(() -> { changePercentBy(100 - currentPercent); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } handler.progressComplete(); }); executor.shutdown(); } public String getCurrentProjectPath() { return currentProjectPath; } public FileHandle getWorkspacePath() { if (!editorConfigVO.lastOpenedSystemPath.isEmpty()) { return new FileHandle(editorConfigVO.lastOpenedSystemPath); } return new FileHandle(defaultWorkspacePath); } public boolean deleteImage(String imageName) { Path path = Paths.get(currentProjectPath, "/assets/orig/images/", imageName); ArrayList<Path> possibleFiles = Lists.newArrayList( path.resolveSibling(path.getFileName() + ".png"), path.resolveSibling(path.getFileName() + ".9.png")); for(Path p : possibleFiles) { if (p.toFile().exists()) return p.toFile().delete(); } throw new IllegalStateException(String.format("The file %s is not found",path.toString())); } public boolean deleteSingleImage(String imageName) { String imagesPath = currentProjectPath + File.separator + IMAGE_DIR_PATH + File.separator; String filePath = imagesPath + imageName + ".png"; return (new File(filePath)).delete(); } public boolean deleteParticle(String particleName) { String particlePath = currentProjectPath + File.separator + PARTICLE_DIR_PATH + File.separator; String filePath = particlePath + particleName; return (new File(filePath)).delete(); } public boolean deleteSpineAnimation(String spineName) { String spinePath = currentProjectPath + File.separator + SPINE_DIR_PATH + File.separator; String filePath = spinePath + spineName; return deleteDirectory(filePath); } public boolean deleteSpriteAnimation(String spineName) { String spritePath = currentProjectPath + File.separator + SPRITE_DIR_PATH + File.separator; String filePath = spritePath + spineName; return deleteDirectory(filePath); } public boolean deleteSpriterAnimation(String spineName) { String spriterPath = currentProjectPath + File.separator + SPRITER_DIR_PATH + File.separator; String filePath = spriterPath + spineName; return deleteDirectory(filePath); } private boolean deleteDirectory(String path) { File file = new File(path); if (file.exists()) { try { FileUtils.deleteDirectory(file); } catch (IOException e) { e.printStackTrace(); } if (!file.exists()) { return true; } } return false; } }