Merge from origin - rednblackgames-master

This commit is contained in:
Jan-Thierry Wegener
2021-06-05 00:15:49 +02:00
47 changed files with 1184 additions and 480 deletions
+3 -1
View File
@@ -9,4 +9,6 @@
Francesco Marongiu (@fgnm) - https://github.com/fgnm
damios (@crykn) - https://github.com/crykn
Raymond Buckley (@raeleus) - https://github.com/raeleus
alyrow (@alyrow) - https://github.com/alyrow
alyrow (@alyrow) - https://github.com/alyrow
6money (@6money) - https://github.com/6money
jantwegener (@jantwegener) - https://github.com/jantwegener
+6
View File
@@ -1,10 +1,16 @@
[0.0.7]
- [BREAK CHANGE] Spine and Sprite animations are now packed into same main atlas pack
- [BREAK CHANGE] Update Project version to `0.2.0`
- Experimental support to Normal Mapping in lights:
* Simple Images
- Add light `intensity`
- Add Box2D Body Sensors
= Editor =
- Use Distance Field fonts for GUI
- Add Editor performance settings (MSAA, OpenGL 3)
- Add multiple atlas packing settings
- Add Import libGDX atlas format
- Huge improvements to Tiled Plugin:
* Sprite and Spine animated Tiles
* UI improvements and general refactoring
Binary file not shown.
Binary file not shown.
+3
View File
@@ -135,6 +135,9 @@
hScrollKnob: scroll-knob-horizontal
}
},
com.kotcrab.vis.ui.util.adapter.SimpleListAdapter$SimpleListAdapterStyle: {
default: {selection: list-selection }
}
com.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle: {
default: {
font: default-font,
@@ -5,6 +5,7 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.NinePatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import games.rednblack.editor.renderer.components.MainItemComponent;
import games.rednblack.editor.renderer.components.NinePatchComponent;
import games.rednblack.editor.renderer.components.TextureRegionComponent;
@@ -148,9 +149,9 @@ public class MainPanelMediator extends Mediator<MainPanel> {
}
private void loadRegion(String name) {
TextureAtlas atlas = plugin.getAPI().getProjectTextureAtlas();
validateNinePatchTextureRegion(atlas.findRegion(name));
viewComponent.setTexture(atlas.findRegion(name));
TextureAtlas.AtlasRegion region = plugin.getAPI().getProjectTextureRegion(name);
validateNinePatchTextureRegion(region);
viewComponent.setTexture(region);
viewComponent.setListeners(plugin.getAPI().getUIStage());
}
@@ -14,6 +14,7 @@ import com.google.common.io.ByteStreams;
import games.rednblack.editor.plugin.tiled.TiledPlugin;
import games.rednblack.editor.plugin.tiled.view.SpineDrawable;
import games.rednblack.editor.renderer.factory.EntityFactory;
import games.rednblack.h2d.extention.spine.ResourceRetrieverAttachmentLoader;
import java.io.File;
import java.io.FileOutputStream;
@@ -86,7 +87,7 @@ public class ResourcesManager {
region = tiledPlugin.getAPI().getSceneLoader().getRm().getTextureRegion(name);
break;
case EntityFactory.SPRITE_TYPE:
region = tiledPlugin.getAPI().getSceneLoader().getRm().getSpriteAnimation(name).getRegions().get(0);
region = tiledPlugin.getAPI().getSceneLoader().getRm().getSpriteAnimation(name).get(0);
break;
}
}
@@ -95,7 +96,8 @@ public class ResourcesManager {
public SpineDrawable getSpineDrawable(String name) {
if (spineDrawableCache.get(name) == null) {
SkeletonJson skeletonJson = new SkeletonJson(tiledPlugin.getAPI().getSceneLoader().getRm().getSkeletonAtlas(name));
ResourceRetrieverAttachmentLoader atlasAttachmentLoader = new ResourceRetrieverAttachmentLoader(name, tiledPlugin.getAPI().getSceneLoader().getRm());
SkeletonJson skeletonJson = new SkeletonJson(atlasAttachmentLoader);
SkeletonData skeletonData = skeletonJson.readSkeletonData(tiledPlugin.getAPI().getSceneLoader().getRm().getSkeletonJSON(name));
Skeleton skeleton = new Skeleton(skeletonData);
@@ -6,12 +6,10 @@ import com.esotericsoftware.spine.SkeletonData;
import com.esotericsoftware.spine.SkeletonJson;
import games.rednblack.editor.plugin.tiled.TiledPlugin;
import games.rednblack.editor.renderer.components.SpineDataComponent;
import games.rednblack.editor.renderer.components.sprite.SpriteAnimationComponent;
import games.rednblack.editor.renderer.components.sprite.SpriteAnimationStateComponent;
import games.rednblack.editor.renderer.utils.ComponentRetriever;
import games.rednblack.h2d.common.command.ReplaceSpineCommandBuilder;
import games.rednblack.h2d.common.factory.IFactory;
import games.rednblack.h2d.extention.spine.SpineObjectComponent;
import games.rednblack.h2d.extention.spine.ResourceRetrieverAttachmentLoader;
public class SpineDrawStrategy extends BasicDrawStrategy {
@@ -47,7 +45,8 @@ public class SpineDrawStrategy extends BasicDrawStrategy {
replaceSpineCommandBuilder.begin(entity);
String animName = tiledPlugin.getSelectedTileName();
replaceSpineCommandBuilder.setAnimationName(animName);
SkeletonJson skeletonJson = new SkeletonJson(tiledPlugin.getAPI().getSceneLoader().getRm().getSkeletonAtlas(animName));
ResourceRetrieverAttachmentLoader atlasAttachmentLoader = new ResourceRetrieverAttachmentLoader(animName, tiledPlugin.getAPI().getSceneLoader().getRm());
SkeletonJson skeletonJson = new SkeletonJson(atlasAttachmentLoader);
replaceSpineCommandBuilder.setSkeletonJson(skeletonJson);
SkeletonData skeletonData = skeletonJson.readSkeletonData((tiledPlugin.getAPI().getSceneLoader().getRm().getSkeletonJSON(animName)));
replaceSpineCommandBuilder.setSkeleton(new Skeleton(skeletonData));
@@ -51,7 +51,7 @@ public class SpriteDrawStrategy extends BasicDrawStrategy {
private Array<TextureAtlas.AtlasRegion> getRegions(String filter) {
// filtering regions by name
Array<TextureAtlas.AtlasRegion> allRegions = tiledPlugin.getAPI().getSceneLoader().getRm().getSpriteAnimation(filter).getRegions();
Array<TextureAtlas.AtlasRegion> allRegions = tiledPlugin.getAPI().getSceneLoader().getRm().getSpriteAnimation(filter);
Array<TextureAtlas.AtlasRegion> regions = new Array<>();
for(TextureAtlas.AtlasRegion region: allRegions) {
if(region.name.contains(filter)) {
@@ -47,12 +47,14 @@ import games.rednblack.editor.view.ui.box.bottom.UIResolutionBoxMediator;
import games.rednblack.editor.view.ui.box.bottom.UISceneBoxMediator;
import games.rednblack.editor.view.ui.box.bottom.UIZoomBoxMediator;
import games.rednblack.editor.view.ui.dialog.AboutDialogMediator;
import games.rednblack.editor.view.ui.dialog.AnimationsPackDialogMediator;
import games.rednblack.editor.view.ui.dialog.AutoTraceDialogMediator;
import games.rednblack.editor.view.ui.dialog.CodeEditorDialogMediator;
import games.rednblack.editor.view.ui.dialog.ConsoleDialogMediator;
import games.rednblack.editor.view.ui.dialog.CreateNewResolutionDialogMediator;
import games.rednblack.editor.view.ui.dialog.CreateNoiseDialogMediator;
import games.rednblack.editor.view.ui.dialog.CreatePlaceholderDialogMediator;
import games.rednblack.editor.view.ui.dialog.ImagesPackDialogMediator;
import games.rednblack.editor.view.ui.dialog.LoadingBarDialogMediator;
import games.rednblack.editor.view.ui.dialog.NewProjectDialogMediator;
import games.rednblack.editor.view.ui.dialog.NodeEditorDialogMediator;
@@ -122,6 +124,8 @@ public class BootstrapViewCommand extends SimpleCommand {
facade.registerMediator(new CreatePlaceholderDialogMediator());
facade.registerMediator(new CreateNoiseDialogMediator());
facade.registerMediator(new ConsoleDialogMediator());
facade.registerMediator(new ImagesPackDialogMediator());
facade.registerMediator(new AnimationsPackDialogMediator());
facade.registerMediator(new SaveProjectDialogMediator());
}
@@ -1,6 +1,7 @@
package games.rednblack.editor.controller.commands.resource;
import com.badlogic.ashley.core.Entity;
import games.rednblack.editor.proxy.ResolutionManager;
import games.rednblack.editor.renderer.components.SpineDataComponent;
import games.rednblack.editor.renderer.data.CompositeItemVO;
import games.rednblack.editor.renderer.data.SceneVO;
@@ -34,7 +35,8 @@ public class DeleteSpineAnimation extends DeleteResourceCommand {
if (projectManager.deleteSpineForAllResolutions(spineItemName)) {
deleteEntitiesWithParticleEffects(sandbox.getRootEntity(), spineItemName);
deleteAllItemsSpineAnimations(spineItemName);
projectManager.loadProjectData(projectManager.getCurrentProjectPath());
ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME);
resolutionManager.rePackProjectImagesForAllResolutions(true);
sendNotification(DONE, spineItemName);
SceneVO vo = sandbox.sceneVoFromItems();
projectManager.saveCurrentProject(vo);
@@ -1,6 +1,7 @@
package games.rednblack.editor.controller.commands.resource;
import com.badlogic.ashley.core.Entity;
import games.rednblack.editor.proxy.ResolutionManager;
import games.rednblack.editor.renderer.components.sprite.SpriteAnimationComponent;
import games.rednblack.editor.renderer.data.CompositeItemVO;
import games.rednblack.editor.renderer.data.SceneVO;
@@ -34,7 +35,8 @@ public class DeleteSpriteAnimation extends DeleteResourceCommand {
if (projectManager.deleteSpriteAnimationForAllResolutions(spriteAnimationName)) {
deleteEntitiesWithSpriteAnimation(sandbox.getRootEntity(), spriteAnimationName);
deleteAllItemsSpriteAnimations(spriteAnimationName);
projectManager.loadProjectData(projectManager.getCurrentProjectPath());
ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME);
resolutionManager.rePackProjectImagesForAllResolutions(true);
facade.sendNotification(DONE, spriteAnimationName);
SceneVO vo = sandbox.sceneVoFromItems();
projectManager.saveCurrentProject(vo);
@@ -25,7 +25,6 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas;
* Created by azakhary on 7/3/2014.
*/
public class SpineAnimData {
public TextureAtlas atlas;
public FileHandle jsonFile;
public String animName;
}
@@ -1,29 +1,9 @@
/*
* ******************************************************************************
* * 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 games.rednblack.editor.data.migrations;
/**
* Created by azakhary on 9/28/2014.
*/
import games.rednblack.editor.renderer.data.ProjectInfoVO;
import games.rednblack.h2d.common.vo.ProjectVO;
public interface IVersionMigrator {
void setProject(String path);
void setProject(String path, ProjectVO vo, ProjectInfoVO projectInfoVO);
boolean doMigration();
}
@@ -20,15 +20,15 @@ package games.rednblack.editor.data.migrations;
import java.io.IOException;
import games.rednblack.editor.data.migrations.migrators.VersionMigTo009;
import games.rednblack.editor.data.migrations.migrators.VersionMigTo011;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import games.rednblack.editor.data.migrations.migrators.*;
import games.rednblack.editor.renderer.data.ProjectInfoVO;
import games.rednblack.h2d.common.vo.ProjectVO;
import org.apache.commons.io.FileUtils;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonWriter;
import games.rednblack.editor.data.migrations.migrators.DummyMig;
import games.rednblack.editor.data.migrations.migrators.VersionMigTo005;
/**
* Created by azakhary on 9/28/2014.
@@ -37,19 +37,29 @@ public class ProjectVersionMigrator {
private String projectPath;
private ProjectVO projectVo;
private ProjectInfoVO projectInfoVO;
private int safetyIterator = 0;
/**
* this is the current supported version, change when data format is changed, and add migration script
*/
public static String dataFormatVersion = "0.1.1";
public static String dataFormatVersion = "0.2.0";
private Json json = new Json();
private final Json json = new Json();
public ProjectVersionMigrator (String projectPath, ProjectVO projectVo) {
this.projectPath = projectPath;
this.projectVo = projectVo;
String prjInfoFilePath = projectPath + "/project.dt";
FileHandle projectInfoFile = Gdx.files.internal(prjInfoFilePath);
String projectInfoContents = "{}";
try {
projectInfoContents = FileUtils.readFileToString(projectInfoFile.file(), "utf-8");
} catch (IOException e) {
e.printStackTrace();
}
projectInfoVO = json.fromJson(ProjectInfoVO.class, projectInfoContents);
json.setOutputType(JsonWriter.OutputType.json);
}
@@ -91,10 +101,14 @@ public class ProjectVersionMigrator {
IVersionMigrator vmt = new VersionMigTo011();
doMigration(vmt, "0.1.1");
}
if (projectVo.projectVersion.equals("0.1.1")) {
IVersionMigrator vmt = new VersionMigTo020();
doMigration(vmt, "0.2.0");
}
}
private void doMigration (IVersionMigrator vmt, String nextVersion) {
vmt.setProject(projectPath);
vmt.setProject(projectPath, projectVo, projectInfoVO);
if (vmt.doMigration()) {
setVersion(nextVersion);
@@ -19,13 +19,15 @@
package games.rednblack.editor.data.migrations.migrators;
import games.rednblack.editor.data.migrations.IVersionMigrator;
import games.rednblack.editor.renderer.data.ProjectInfoVO;
import games.rednblack.h2d.common.vo.ProjectVO;
/**
* Created by azakhary on 1/29/2015.
*/
public class DummyMig implements IVersionMigrator {
@Override
public void setProject(String path) {
public void setProject(String path, ProjectVO vo, ProjectInfoVO projectInfoVO) {
}
@@ -21,6 +21,7 @@ package games.rednblack.editor.data.migrations.migrators;
import java.io.File;
import java.io.IOException;
import games.rednblack.h2d.common.vo.ProjectVO;
import org.apache.commons.io.FileUtils;
import com.badlogic.gdx.Gdx;
@@ -31,9 +32,7 @@ import com.badlogic.gdx.utils.JsonWriter;
import games.rednblack.editor.data.migrations.IVersionMigrator;
import games.rednblack.editor.HyperLap2DFacade;
import games.rednblack.editor.proxy.ProjectManager;
import games.rednblack.editor.proxy.ResolutionManager;
import games.rednblack.editor.renderer.data.ProjectInfoVO;
import games.rednblack.editor.renderer.data.ResolutionEntryVO;
/**
* Created by azakhary on 9/28/2014.
@@ -48,7 +47,7 @@ public class VersionMigTo005 implements IVersionMigrator {
private ProjectManager projectManager;
@Override
public void setProject(String path) {
public void setProject(String path, ProjectVO vo, ProjectInfoVO projectInfoVO) {
facade = HyperLap2DFacade.getInstance();
projectManager = facade.retrieveProxy(ProjectManager.NAME);
projectPath = path;
@@ -57,7 +56,6 @@ public class VersionMigTo005 implements IVersionMigrator {
@Override
public boolean doMigration() {
// Rename folder animations to spine-animations in orig (if exist);
File animationsDir = new File(projectPath + File.separator + "assets" + File.separator + "orig" + File.separator + "animations");
if (animationsDir.exists() && animationsDir.isDirectory()) {
@@ -73,12 +71,6 @@ public class VersionMigTo005 implements IVersionMigrator {
projectInfoContents = FileUtils.readFileToString(projectInfoFile.file(), "utf-8");
ProjectInfoVO currentProjectInfoVO = json.fromJson(ProjectInfoVO.class, projectInfoContents);
projectManager.currentProjectInfoVO = currentProjectInfoVO;
// run through all resolutions and remake animations for all
for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) {
ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME);
resolutionManager.createResizedAnimations(resolutionEntryVO);
}
} catch (IOException e) {
e.printStackTrace();
}
@@ -27,6 +27,8 @@ import com.badlogic.gdx.utils.JsonWriter;
import games.rednblack.editor.HyperLap2DFacade;
import games.rednblack.editor.data.migrations.IVersionMigrator;
import games.rednblack.editor.proxy.ProjectManager;
import games.rednblack.editor.renderer.data.ProjectInfoVO;
import games.rednblack.h2d.common.vo.ProjectVO;
import org.apache.commons.io.FileUtils;
import java.io.File;
@@ -46,7 +48,7 @@ public class VersionMigTo009 implements IVersionMigrator {
private ProjectManager projectManager;
@Override
public void setProject(String path) {
public void setProject(String path, ProjectVO vo, ProjectInfoVO projectInfoVO) {
facade = HyperLap2DFacade.getInstance();
projectManager = facade.retrieveProxy(ProjectManager.NAME);
projectPath = path;
@@ -6,10 +6,11 @@ import com.badlogic.gdx.utils.JsonValue;
import com.badlogic.gdx.utils.JsonWriter;
import games.rednblack.editor.data.migrations.IVersionMigrator;
import games.rednblack.editor.renderer.data.GraphVO;
import games.rednblack.editor.renderer.data.ProjectInfoVO;
import games.rednblack.h2d.common.vo.ProjectVO;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
public class VersionMigTo011 implements IVersionMigrator {
@@ -19,7 +20,7 @@ public class VersionMigTo011 implements IVersionMigrator {
private String projectPath;
@Override
public void setProject(String path) {
public void setProject(String path, ProjectVO vo, ProjectInfoVO projectInfoVO) {
projectPath = path;
json.setOutputType(JsonWriter.OutputType.json);
}
@@ -0,0 +1,124 @@
package games.rednblack.editor.data.migrations.migrators;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.PixmapIO;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonWriter;
import games.rednblack.editor.data.migrations.IVersionMigrator;
import games.rednblack.editor.proxy.ProjectManager;
import games.rednblack.editor.renderer.data.ProjectInfoVO;
import games.rednblack.editor.utils.ImportUtils;
import games.rednblack.h2d.common.vo.ProjectVO;
import games.rednblack.editor.renderer.data.TexturePackVO;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.io.IOException;
public class VersionMigTo020 implements IVersionMigrator {
private final Json json = new Json();
private String projectPath;
private ProjectVO projectVO;
private ProjectInfoVO projectInfoVO;
@Override
public void setProject(String path, ProjectVO vo, ProjectInfoVO projectInfoVO) {
projectPath = path;
projectVO = vo;
this.projectInfoVO = projectInfoVO;
json.setOutputType(JsonWriter.OutputType.json);
}
@Override
public boolean doMigration() {
TexturePackVO mainPack = new TexturePackVO();
mainPack.name = "main";
projectInfoVO.imagesPacks.put("main", mainPack);
String res = projectVO.lastOpenResolution.isEmpty() ? "orig" : projectVO.lastOpenResolution;
FileHandle pack = new FileHandle(projectPath + "/assets/" + res + "/pack/pack.atlas");
TextureAtlas.TextureAtlasData mainAtlas = new TextureAtlas.TextureAtlasData(pack, pack.parent(), false);
for (TextureAtlas.TextureAtlasData.Region region : new Array.ArrayIterator<>(mainAtlas.getRegions())) {
projectInfoVO.imagesPacks.get("main").regions.add(region.name);
}
TexturePackVO mainAnimPack = new TexturePackVO();
mainAnimPack.name = "main";
projectInfoVO.animationsPacks.put("main", mainAnimPack);
String spriteAnimationsPath = projectPath + File.separator + "assets/orig" + File.separator + "sprite-animations";
FileHandle sourceDir = new FileHandle(spriteAnimationsPath);
for (FileHandle entry : sourceDir.list()) {
if (entry.file().isDirectory()) {
String animName = FilenameUtils.removeExtension(entry.file().getName());
FileHandle atlasTargetPath = new FileHandle(new File(spriteAnimationsPath + File.separator + animName + File.separator + animName + ".atlas"));
TextureAtlas.TextureAtlasData atlas = new TextureAtlas.TextureAtlasData(atlasTargetPath, atlasTargetPath.parent(), false);
for (TextureAtlas.TextureAtlasData.Region region : new Array.ArrayIterator<>(atlas.getRegions())) {
projectInfoVO.animationsPacks.get("main").regions.add(region.name);
}
try {
ImportUtils.unpackAtlasIntoTmpFolder(atlasTargetPath.file(), null,projectPath + File.separator + ProjectManager.IMAGE_DIR_PATH);
} catch (Exception ignore) {
}
for (TextureAtlas.TextureAtlasData.Page page : new Array.ArrayIterator<>(atlas.getPages())) {
if (page.textureFile != null)
page.textureFile.delete();
}
}
}
String spineAnimationsPath = projectPath + File.separator + "assets/orig" + File.separator + "spine-animations";
FileHandle spineDir = new FileHandle(spineAnimationsPath);
for (FileHandle entry : spineDir.list()) {
if (entry.file().isDirectory()) {
String animName = FilenameUtils.removeExtension(entry.file().getName());
FileHandle atlasTargetPath = new FileHandle(new File(spineAnimationsPath + File.separator + animName + File.separator + animName + ".atlas"));
TextureAtlas.TextureAtlasData atlas = new TextureAtlas.TextureAtlasData(atlasTargetPath, atlasTargetPath.parent(), false);
for (TextureAtlas.TextureAtlasData.Region region : new Array.ArrayIterator<>(atlas.getRegions())) {
projectInfoVO.animationsPacks.get("main").regions.add(animName+region.name);
}
try {
ImportUtils.unpackAtlasIntoTmpFolder(atlasTargetPath.file(), animName, projectPath + File.separator + ProjectManager.IMAGE_DIR_PATH);
} catch (Exception ignore) {
}
for (TextureAtlas.TextureAtlasData.Page page : new Array.ArrayIterator<>(atlas.getPages())) {
if (page.textureFile != null)
page.textureFile.delete();
}
atlasTargetPath.delete();
}
}
Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pixmap.setColor(Color.WHITE);
pixmap.fill();
FileHandle whitePixel = new FileHandle(projectPath + File.separator + "assets/orig/images" + File.separator + "white-pixel.png");
PixmapIO.writePNG(whitePixel, pixmap);
projectInfoVO.imagesPacks.get("main").regions.add("white-pixel");
try {
FileUtils.writeStringToFile(new File(projectPath + "/project.dt"), projectInfoVO.constructJsonString(), "utf-8");
} catch (IOException e) {
return false;
}
pack.delete();
return true;
}
}
@@ -109,9 +109,9 @@ public class PluginManager extends Proxy implements PluginAPI {
}
@Override
public TextureAtlas getProjectTextureAtlas() {
public TextureAtlas.AtlasRegion getProjectTextureRegion(String regionName) {
ResourceManager resourceManager = facade.retrieveProxy(ResourceManager.NAME);
return resourceManager.getTextureAtlas();
return (TextureAtlas.AtlasRegion) resourceManager.getTextureRegion(regionName);
}
@Override
@@ -20,9 +20,14 @@ package games.rednblack.editor.proxy;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.PixmapIO;
import com.badlogic.gdx.tools.texturepacker.TexturePacker.Settings;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonReader;
import com.badlogic.gdx.utils.JsonValue;
import com.kotcrab.vis.ui.util.dialog.Dialogs;
import games.rednblack.editor.HyperLap2DFacade;
import games.rednblack.editor.data.manager.PreferencesManager;
@@ -105,14 +110,6 @@ public class ProjectManager extends Proxy {
}
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);
@@ -123,9 +120,13 @@ public class ProjectManager extends Proxy {
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"));
Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pixmap.setColor(Color.WHITE);
pixmap.fill();
FileHandle whitePixel = new FileHandle(projPath + File.separator + "assets/orig/images" + File.separator + "white-pixel.png");
PixmapIO.writePNG(whitePixel, pixmap);
// create project file
ProjectVO projVo = new ProjectVO();
@@ -138,6 +139,13 @@ public class ProjectManager extends Proxy {
projInfoVo.originalResolution.width = width;
projInfoVo.originalResolution.height = height;
projInfoVo.pixelToWorld = pixelPerWorldUnit;
TexturePackVO mainPack = new TexturePackVO();
mainPack.name = "main";
mainPack.regions.add("white-pixel");
projInfoVo.imagesPacks.put("main", mainPack);
TexturePackVO mainAnimPack = new TexturePackVO();
mainAnimPack.name = "main";
projInfoVo.animationsPacks.put("main", mainAnimPack);
//TODO: add project orig resolution setting
currentProjectVO = projVo;
@@ -187,19 +195,6 @@ public class ProjectManager extends Proxy {
File prjFile = new File(prjFilePath);
if (!prjFile.isDirectory()) {
if (!prjFile.exists()) {
ProjectVO projVoEmpty = new ProjectVO();
projVoEmpty.projectName = prjFile.getName();
projVoEmpty.projectVersion = ProjectVersionMigrator.dataFormatVersion;
try {
FileUtils.writeStringToFile(prjFile, projVoEmpty.constructJsonString(), "utf-8");
} catch (IOException e) {
e.printStackTrace();
}
}
String projectContents = null;
try {
projectContents = FileUtils.readFileToString(projectFile.file(), "utf-8");
@@ -225,10 +220,10 @@ public class ProjectManager extends Proxy {
} else {
resolutionManager.currentResolutionName = resolution;
currentProjectVO.lastOpenResolution = resolutionManager.currentResolutionName;
saveCurrentProject();
}
currentProjectPath = projectPath;
saveCurrentProject();
checkForConsistency(projectPath);
loadProjectData(projectPath);
@@ -304,12 +299,6 @@ public class ProjectManager extends Proxy {
}
}
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);
@@ -410,12 +399,7 @@ public class ProjectManager extends Proxy {
newFile.mkdir();
}
// The filename should not be changed because the particle effects contain the name in their
// configuration. Unfortunately though, the texture packer does not support the underscore because
// any underscore in the texture packer is considered an image index. More info here:
// https://github.com/libgdx/libgdx/wiki/Texture-packer#image-indexes
// So, long story short, we MUST remove the underscore.
ImageIO.write(bufferedImage, "png", new File(targetPath + "/" + handle.name().replace("_", "")));
ImageIO.write(bufferedImage, "png", new File(targetPath + "/" + handle.name()));
} catch (IOException e) {
e.printStackTrace();
}
@@ -455,7 +439,6 @@ public class ProjectManager extends Proxy {
if (!currentProjectVO.projectMainExportPath.isEmpty()) {
exportFonts(currentProjectVO.projectMainExportPath);
}
exportStyles(defaultBuildPath);
SceneDataManager sceneDataManager = facade.retrieveProxy(SceneDataManager.NAME);
sceneDataManager.buildScenes(defaultBuildPath);
if (!currentProjectVO.projectMainExportPath.isEmpty()) {
@@ -463,18 +446,6 @@ public class ProjectManager extends Proxy {
}
}
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);
@@ -482,8 +453,7 @@ public class ProjectManager extends Proxy {
File fileTarget = new File(targetPath + "/" + shadersDirectory.name());
try {
FileUtils.copyDirectory(shadersDirectory.file(), fileTarget);
} catch (IOException e) {
e.printStackTrace();
} catch (IOException ignore) {
}
}
@@ -494,8 +464,7 @@ public class ProjectManager extends Proxy {
File fileTarget = new File(targetPath + "/" + particlesDirectory.name());
try {
FileUtils.copyDirectory(particlesDirectory.file(), fileTarget);
} catch (IOException e) {
e.printStackTrace();
} catch (IOException ignore) {
}
}
@@ -506,8 +475,7 @@ public class ProjectManager extends Proxy {
File fileTarget = new File(targetPath + "/" + particlesDirectory.name());
try {
FileUtils.copyDirectory(particlesDirectory.file(), fileTarget);
} catch (IOException e) {
e.printStackTrace();
} catch (IOException ignore) {
}
}
@@ -518,18 +486,15 @@ public class ProjectManager extends Proxy {
File fileTarget = new File(targetPath + "/" + fontsDirectory.name());
try {
FileUtils.copyDirectory(fontsDirectory.file(), fileTarget);
} catch (IOException e) {
e.printStackTrace();
} catch (IOException ignore) {
}
}
private void exportAnimations(String targetPath) {
exportSpineAnimationForResolution("orig", targetPath);
exportSpriteAnimationForResolution("orig", targetPath);
for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) {
exportSpineAnimationForResolution(resolutionEntryVO.name, targetPath);
exportSpriteAnimationForResolution(resolutionEntryVO.name, targetPath);
}
}
@@ -548,21 +513,6 @@ public class ProjectManager extends Proxy {
}
}
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 exportPacks(String targetPath) {
String srcPath = currentProjectPath + "/assets";
FileHandle assetDirectoryHandle = Gdx.files.absolute(srcPath);
@@ -681,6 +631,7 @@ public class ProjectManager extends Proxy {
private boolean deleteSingleImage(String resolutionName, String imageName) {
String imagesPath = currentProjectPath + "/assets/" + resolutionName + "/images" + File.separator;
String filePath = imagesPath + imageName + ".png";
deleteRegionFromPack(currentProjectInfoVO.imagesPacks, imageName);
if (!(new File(filePath)).delete()) {
filePath = imagesPath + imageName + ".9.png";
return (new File(filePath)).delete();
@@ -711,6 +662,18 @@ public class ProjectManager extends Proxy {
private boolean deleteSpineAnimation(String resolutionName, String spineName) {
String spinePath = currentProjectPath + "/assets/" + resolutionName + "/spine-animations" + File.separator;
String filePath = spinePath + spineName;
FileHandle jsonPath = new FileHandle(filePath + File.separator + spineName + ".json");
JsonValue root = new JsonReader().parse(jsonPath);
for (JsonValue skinMap = root.getChild("skins"); skinMap != null; skinMap = skinMap.next) {
for (JsonValue slotEntry = skinMap.getChild("attachments"); slotEntry != null; slotEntry = slotEntry.next) {
for (JsonValue entry = slotEntry.child; entry != null; entry = entry.next) {
String name = spineName + entry.getString("name", entry.name);
deleteSingleImage(resolutionName, name);
deleteRegionFromPack(currentProjectInfoVO.animationsPacks, name);
}
}
}
return deleteDirectory(filePath);
}
@@ -722,12 +685,25 @@ public class ProjectManager extends Proxy {
return deleteSpineAnimation("orig", spineName);
}
private boolean deleteSpriteAnimation(String resolutionName, String spineName) {
private boolean deleteSpriteAnimation(String resolutionName, String spriteName) {
String spritePath = currentProjectPath + "/assets/" + resolutionName + "/sprite-animations" + File.separator;
String filePath = spritePath + spineName;
String filePath = spritePath + spriteName;
FileHandle imagesPath = new FileHandle(currentProjectPath + "/assets/" + resolutionName + "/images" + File.separator);
String prefix = spriteName + "_";
for (FileHandle f : imagesPath.list()) {
if (f.nameWithoutExtension().startsWith(prefix)) {
f.delete();
}
}
deleteRegionFromPack(currentProjectInfoVO.animationsPacks, spriteName);
return deleteDirectory(filePath);
}
public void deleteRegionFromPack(HashMap<String, TexturePackVO> map, String region) {
for (TexturePackVO vo : map.values())
vo.regions.remove(region);
}
public boolean deleteSpriteAnimationForAllResolutions(String spineName) {
for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) {
if(!deleteSpriteAnimation(resolutionEntryVO.name, spineName))
@@ -29,15 +29,15 @@ import java.util.concurrent.Executors;
import javax.imageio.ImageIO;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.ObjectMap;
import com.kotcrab.vis.ui.util.dialog.Dialogs;
import games.rednblack.editor.renderer.data.TexturePackVO;
import games.rednblack.h2d.common.MsgAPI;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.tools.texturepacker.TexturePacker;
import com.badlogic.gdx.tools.texturepacker.TextureUnpacker;
import com.badlogic.gdx.utils.Array;
import com.mortennobel.imagescaling.ResampleOp;
import games.rednblack.editor.view.stage.Sandbox;
@@ -152,7 +152,6 @@ public class ResolutionManager extends Proxy {
copyTexturesFromTo(sourcePath, targetPath);
int resizeWarnings = resizeTextures(targetPath, resolutionEntryVO);
rePackProjectImages(resolutionEntryVO);
createResizedAnimations(resolutionEntryVO);
changePercentBy(5);
if (resizeWarnings > 0) {
Dialogs.showOKDialog(Sandbox.getInstance().getUIStage(), "Warning", resizeWarnings + " images were not resized for smaller resolutions due to already small size ( < 3px )");
@@ -177,144 +176,10 @@ public class ResolutionManager extends Proxy {
//handler.progressChanged(currentPercent);
}
public void createResizedAnimations(ResolutionEntryVO resolution) {
ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME);
String currProjectPath = projectManager.getCurrentProjectPath();
// Unpack spine orig
File spineSourceDir = new File(currProjectPath + File.separator + "assets/orig/spine-animations");
if (spineSourceDir.exists()) {
for (File entry : spineSourceDir.listFiles()) {
if (entry.isDirectory()) {
String animName = FilenameUtils.removeExtension(entry.getName());
createResizedSpineAnimation(animName, resolution);
}
}
}
//Unpack sprite orig
File spriteSourceDir = new File(currProjectPath + File.separator + "assets/orig/sprite-animations");
if (spriteSourceDir.exists()) {
for (File entry : spriteSourceDir.listFiles()) {
if (entry.isDirectory()) {
String animName = FilenameUtils.removeExtension(entry.getName());
createResizedSpriteAnimation(animName, resolution);
}
}
}
}
public void createResizedSpriteAnimation(String animName, ResolutionEntryVO resolution) {
ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME);
String currProjectPath = projectManager.getCurrentProjectPath();
File animAtlasFile = new File(currProjectPath + File.separator + "assets/orig/sprite-animations/" + animName + "/" + animName + ".atlas");
String tmpPath = currProjectPath + File.separator + "assets/orig/sprite-animations/" + animName + "/tmp";
File tmpFolder = new File(tmpPath);
try {
FileUtils.forceMkdir(new File(currProjectPath + File.separator + "assets/" + resolution.name + "/sprite-animations/"));
FileUtils.forceMkdir(new File(currProjectPath + File.separator + "assets/" + resolution.name + "/spine-animations/" + animName));
String targetPath = currProjectPath + File.separator + "assets/" + resolution.name + "/sprite-animations/" + animName;
File targetFolder = new File(targetPath);
unpackAtlasIntoTmpFolder(animAtlasFile, tmpPath);
resizeImagesTmpDirToResolution(animName, tmpFolder, resolution, targetFolder);
FileUtils.deleteDirectory(tmpFolder);
} catch (IOException e) {
e.printStackTrace();
}
}
public void unpackAtlasIntoTmpFolder(File atlasFile, String tmpDir) {
FileHandle atlasFileHandle = new FileHandle(atlasFile);
TextureAtlas.TextureAtlasData atlasData = new TextureAtlas.TextureAtlasData(atlasFileHandle, atlasFileHandle.parent(), false);
TextureUnpacker unpacker = new TextureUnpacker();
unpacker.splitAtlas(atlasData, tmpDir);
}
public void createResizedSpineAnimation(String animName, ResolutionEntryVO resolution) {
ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME);
String currProjectPath = projectManager.getCurrentProjectPath();
File animAtlasFile = new File(currProjectPath + File.separator + "assets/orig/spine-animations/" + animName + "/" + animName + ".atlas");
String tmpPath = currProjectPath + File.separator + "assets/orig/spine-animations/" + animName + "/tmp";
File tmpFolder = new File(tmpPath);
try {
FileUtils.forceMkdir(new File(currProjectPath + File.separator + "assets/" + resolution.name + "/spine-animations/"));
FileUtils.forceMkdir(new File(currProjectPath + File.separator + "assets/" + resolution.name + "/spine-animations/" + animName));
String targetPath = currProjectPath + File.separator + "assets/" + resolution.name + "/spine-animations/" + animName;
File targetFolder = new File(targetPath);
unpackAtlasIntoTmpFolder(animAtlasFile, tmpPath);
resizeImagesTmpDirToResolution(animName, tmpFolder, resolution, targetFolder);
FileUtils.deleteDirectory(tmpFolder);
} catch (IOException e) {
e.printStackTrace();
}
}
public void resizeSpriteAnimationForAllResolutions(String animName, ProjectInfoVO currentProjectInfoVO) {
ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME);
String currProjectPath = projectManager.getCurrentProjectPath();
File atlasFile = new File(currProjectPath + File.separator + "assets" + File.separator + "orig" + File.separator + "sprite-animations" + File.separator + animName + File.separator + animName + ".atlas");
String tmpDir = currProjectPath + File.separator + "assets" + File.separator + "orig" + File.separator + "sprite-animations" + File.separator + animName + File.separator + "tmp";
File sourceFolder = new File(tmpDir);
unpackAtlasIntoTmpFolder(atlasFile, tmpDir);
try {
for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) {
String spriteAnimationsRoot = currProjectPath + File.separator + "assets" + File.separator + resolutionEntryVO.name + File.separator + "sprite-animations";
FileUtils.forceMkdir(new File(spriteAnimationsRoot));
String targetPath = spriteAnimationsRoot + File.separator + animName;
File targetFolder = new File(targetPath);
resizeImagesTmpDirToResolution(animName, sourceFolder, resolutionEntryVO, targetFolder);
}
FileUtils.deleteDirectory(sourceFolder);
} catch (IOException e) {
e.printStackTrace();
}
}
public void resizeSpineAnimationForAllResolutions(File atlasFile, ProjectInfoVO currentProjectInfoVO) {
String fileNameWithOutExt = FilenameUtils.removeExtension(atlasFile.getName());
ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME);
String tmpDir = projectManager.getCurrentProjectPath() + "/assets/orig/spine-animations" + File.separator + fileNameWithOutExt + File.separator + "tmp";
File sourceFolder = new File(tmpDir);
unpackAtlasIntoTmpFolder(atlasFile, tmpDir);
try {
for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) {
FileUtils.forceMkdir(new File(projectManager.getCurrentProjectPath() + File.separator +
"assets" + File.separator + resolutionEntryVO.name + File.separator + "spine-animations"));
String targetPath = projectManager.getCurrentProjectPath() + File.separator + "assets" +
File.separator + resolutionEntryVO.name + File.separator + "spine-animations" + File.separator + fileNameWithOutExt;
FileUtils.forceMkdir(new File(targetPath));
File targetFolder = new File(targetPath);
resizeImagesTmpDirToResolution(atlasFile.getName(), sourceFolder, resolutionEntryVO, targetFolder);
}
FileUtils.deleteDirectory(sourceFolder);
} catch (IOException e) {
e.printStackTrace();
}
}
public void rePackProjectImages(ResolutionEntryVO resEntry) {
ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME);
TexturePacker.Settings settings = projectManager.getTexturePackerSettings();
TexturePacker tp = new TexturePacker(settings);
String sourcePath = projectManager.getCurrentProjectPath() + "/assets/" + resEntry.name + "/images";
String outputPath = projectManager.getCurrentProjectPath() + "/assets/" + resEntry.name + "/pack";
@@ -328,15 +193,36 @@ public class ResolutionManager extends Proxy {
e.printStackTrace();
}
ObjectMap<String, TexturePacker> packerMap = new ObjectMap<>();
ObjectMap<String, String> regionsReverse = new ObjectMap<>();
for (TexturePackVO packVO : projectManager.currentProjectInfoVO.imagesPacks.values()) {
String name = packVO.name.equals("main") ? "pack" : packVO.name;
packerMap.put(name, new TexturePacker(settings));
for (String region : packVO.regions)
regionsReverse.put(region, name);
}
for (TexturePackVO packVO : projectManager.currentProjectInfoVO.animationsPacks.values()) {
String name = packVO.name.equals("main") ? "pack" : packVO.name;
if (packerMap.get(name) == null)
packerMap.put(name, new TexturePacker(settings));
for (String region : packVO.regions)
regionsReverse.put(region, name);
}
for (FileHandle entry : sourceDir.list()) {
String filename = entry.file().getName();
String extension = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
if (extension.equals("png")) {
if (entry.extension().equals("png")) {
String name = regionsReverse.get(entry.nameWithoutExtension().replace(".9", "").replaceAll("_[0-9]+", ""));
name = name == null ? "pack" : name;
TexturePacker tp = packerMap.get(name);
tp.addImage(entry.file());
}
}
tp.pack(outputDir, "pack");
for (String name : packerMap.keys()) {
TexturePacker tp = packerMap.get(name);
tp.pack(outputDir, name);
}
}
private int resizeTextures(String path, ResolutionEntryVO resolution) {
@@ -18,6 +18,7 @@ import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
import com.kotcrab.vis.ui.VisUI;
import com.talosvfx.talos.runtime.ParticleEffectDescriptor;
@@ -29,6 +30,7 @@ import games.rednblack.editor.renderer.data.*;
import games.rednblack.editor.renderer.utils.H2DSkinLoader;
import games.rednblack.editor.renderer.utils.ShadedDistanceFieldFont;
import games.rednblack.editor.view.ui.widget.actors.basic.WhitePixel;
import games.rednblack.h2d.extension.talos.ResourceRetrieverAssetProvider;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
@@ -57,10 +59,10 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
private final HashMap<String, ParticleEffect> particleEffects = new HashMap<>(1);
private final HashMap<String, ParticleEffectDescriptor> talosVFXs = new HashMap<>(1);
private final HashMap<String, FileHandle> talosVFXsFiles = new HashMap<>(1);
private TextureAtlas currentProjectAtlas;
private HashMap<String, TextureAtlas> currentProjectAtlas = new HashMap<>(1);
private final HashMap<String, SpineAnimData> spineAnimAtlases = new HashMap<>();
private final HashMap<String, TextureAtlas> spriteAnimAtlases = new HashMap<>();
private final HashMap<String, Array<TextureAtlas.AtlasRegion>> spriteAnimAtlases = new HashMap<>();
private final HashMap<FontSizePair, BitmapFont> bitmapFonts = new HashMap<>();
private final HashMap<String, ShaderProgram> shaderPrograms = new HashMap<>(1);
@@ -144,17 +146,17 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
@Override
public TextureRegion getTextureRegion(String name) {
TextureRegion reg = currentProjectAtlas.findRegion(name);
if(reg == null) {
reg = defaultRegion;
for (TextureAtlas atlas : currentProjectAtlas.values()) {
TextureRegion region = atlas.findRegion(name);
if (region != null)
return region;
}
return reg;
return defaultRegion;
}
public TextureAtlas getTextureAtlas() {
return currentProjectAtlas;
@Override
public TextureAtlas getTextureAtlas(String atlasName) {
return currentProjectAtlas.get(atlasName);
}
@Override
@@ -167,12 +169,6 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
return talosVFXsFiles.get(name);
}
@Override
public TextureAtlas getSkeletonAtlas(String animationName) {
SpineAnimData animData = spineAnimAtlases.get(animationName);
return animData.atlas;
}
/**
* Sets working resolution, please set before doing any loading
* @param resolution String resolution name, default is "orig" later use resolution names created in editor
@@ -192,7 +188,7 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
}
@Override
public TextureAtlas getSpriteAnimation(String animationName) {
public Array<TextureAtlas.AtlasRegion> getSpriteAnimation(String animationName) {
return spriteAnimAtlases.get(animationName);
}
@@ -206,7 +202,11 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
@Override
public boolean hasTextureRegion(String regionName) {
return currentProjectAtlas.findRegion(regionName) != null;
for (TextureAtlas atlas : currentProjectAtlas.values()) {
if (atlas.findRegion(regionName) != null)
return true;
}
return false;
}
@Override
@@ -228,8 +228,7 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
public void loadCurrentProjectData(String projectPath, String curResolution) {
packResolutionName = curResolution;
loadCurrentProjectAssets(projectPath + "/assets/" + curResolution + "/pack/pack.atlas");
loadCurrentProjectSkin(projectPath + "/assets/orig/styles");
loadCurrentProjectAssets(projectPath + "/assets/" + curResolution + "/pack");
loadCurrentProjectParticles(projectPath + "/assets/orig/particles");
loadCurrentProjectTalosVFXs(projectPath + "/assets/orig/talos-vfx");
loadCurrentProjectSpineAnimations(projectPath + "/assets/", curResolution);
@@ -247,7 +246,13 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
if (file.isDirectory() || filename.endsWith(".DS_Store")) continue;
ParticleEffect particleEffect = new ParticleEffect();
particleEffect.load(Gdx.files.internal(file.getAbsolutePath()), currentProjectAtlas, "");
particleEffect.loadEmitters(Gdx.files.internal(file.getAbsolutePath()));
for (TextureAtlas atlas : currentProjectAtlas.values()) {
try {
particleEffect.loadEmitterImages(atlas, "");
break;
} catch (Exception ignore) { }
}
particleEffects.put(filename, particleEffect);
}
}
@@ -261,7 +266,7 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
String filename = file.getName();
if (file.isDirectory() || filename.endsWith(".DS_Store") || filename.endsWith("shdr") || filename.endsWith(".fga")) continue;
AtlasAssetProvider assetProvider = new AtlasAssetProvider(currentProjectAtlas);
ResourceRetrieverAssetProvider assetProvider = new ResourceRetrieverAssetProvider(this);
assetProvider.setAssetHandler(ShaderDescriptor.class, this::findShaderDescriptorOnLoad);
assetProvider.setAssetHandler(VectorField.class, this::findVectorFieldDescriptorOnLoad);
ParticleEffectDescriptor effectDescriptor = new ParticleEffectDescriptor();
@@ -309,10 +314,8 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
for (FileHandle entry : sourceDir.list()) {
if (entry.file().isDirectory()) {
String animName = FilenameUtils.removeExtension(entry.file().getName());
TextureAtlas atlas = new TextureAtlas(Gdx.files.internal(path + curResolution + "/spine-animations/" + File.separator + animName + File.separator + animName + ".atlas"));
FileHandle animJsonFile = Gdx.files.internal(entry.file().getAbsolutePath() + File.separator + animName + ".json");
SpineAnimData data = new SpineAnimData();
data.atlas = atlas;
data.jsonFile = animJsonFile;
data.animName = animName;
spineAnimAtlases.put(animName, data);
@@ -323,28 +326,29 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
private void loadCurrentProjectSpriteAnimations(String path, String curResolution) {
spriteAnimAtlases.clear();
FileHandle sourceDir = new FileHandle(path + curResolution + File.separator + "sprite-animations");
FileHandle sourceDir = new FileHandle(path + "orig" + File.separator + "sprite-animations");
for (FileHandle entry : sourceDir.list()) {
if (entry.file().isDirectory()) {
String animName = FilenameUtils.removeExtension(entry.file().getName());
FileHandle atlasFile = Gdx.files.internal(entry.file().getAbsolutePath() + File.separator + animName + ".atlas");
if (!atlasFile.exists())
continue;
try {
TextureAtlas atlas = new TextureAtlas(atlasFile);
spriteAnimAtlases.put(animName, atlas);
} catch (Exception e) {
e.printStackTrace();
Array<TextureAtlas.AtlasRegion> regions = null;
for (TextureAtlas atlas : currentProjectAtlas.values()) {
regions = atlas.findRegions(animName);
if (regions.size > 0)
break;
}
if (regions != null)
spriteAnimAtlases.put(animName, regions);
}
}
}
public void loadCurrentProjectAssets(String packPath) {
try {
currentProjectAtlas = new TextureAtlas(Gdx.files.getFileHandle(packPath, Files.FileType.Internal));
} catch (Exception e) {
currentProjectAtlas = new TextureAtlas();
public void loadCurrentProjectAssets(String packFolderPath) {
FileHandle folder = new FileHandle(packFolderPath);
for (FileHandle file : folder.list()) {
if (file.extension().equals("atlas")) {
String name = file.nameWithoutExtension().equals("pack") ? "main" : file.nameWithoutExtension();
currentProjectAtlas.put(name, new TextureAtlas(file));
}
}
}
@@ -432,27 +436,6 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
}
}
/**
* @param fontPath
* TODO currently useless, but could be reworked to include stuff from Skin Composer
* @deprecated
*/
@Deprecated
private void loadCurrentProjectSkin(String fontPath) {
/*
File styleFile = new File(fontPath, "styles.dt");
FileHandle f = new FileHandle(styleFile);
if (styleFile.isFile() && styleFile.exists()) {
projectSkin = new MySkin(f);
ObjectMap<String, BitmapFont> map = projectSkin.getAll(BitmapFont.class);
for (ObjectMap.Entry<String, BitmapFont> entry : map.entries()) {
projectSkin.getFont(entry.key).getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
}
}
*/
}
public FileHandle getTTFSafely(String fontName) throws IOException {
FontManager fontManager = facade.retrieveProxy(FontManager.NAME);
@@ -517,14 +500,10 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
return spineAnimAtlases;
}
public HashMap<String, TextureAtlas> getProjectSpriteAnimationsList() {
public HashMap<String, Array<TextureAtlas.AtlasRegion>> getProjectSpriteAnimationsList() {
return spriteAnimAtlases;
}
public TextureAtlas getProjectAssetsList() {
return currentProjectAtlas;
}
public HashMap<String, ParticleEffect> getProjectParticleList() {
return particleEffects;
}
@@ -549,9 +528,4 @@ public class ResourceManager extends Proxy implements IResourceRetriever {
public HashMap<String, ShaderProgram> getShaders() {
return shaderPrograms;
}
@Override
public TextureAtlas getMainPack() {
return currentProjectAtlas;
}
}
@@ -22,7 +22,6 @@ import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.utils.Array;
import com.kotcrab.vis.ui.widget.file.FileTypeFilter;
import org.apache.commons.io.FilenameUtils;
import java.io.BufferedReader;
import java.io.File;
@@ -138,23 +137,11 @@ public class ImportUtils {
return regions.get(regions.size - 1).index == regions.size - 1;
}
public static 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;
//In atlas file format the name of the png is is preceded by an empty line
if (line.trim().length() == 0) {
line = reader.readLine();
imgs.add(new File(FilenameUtils.getFullPath(fileHandle.path()) + line));
}
}
} catch (IOException e) {
e.printStackTrace();
}
return imgs;
public static void unpackAtlasIntoTmpFolder(File atlasFile, String prefix, String tmpDir) {
FileHandle atlasFileHandle = new FileHandle(atlasFile);
TextureAtlas.TextureAtlasData atlasData = new TextureAtlas.TextureAtlasData(atlasFileHandle, atlasFileHandle.parent(), false);
TextureUnpacker unpacker = new TextureUnpacker();
unpacker.splitAtlas(atlasData, prefix, tmpDir);
}
public static String getAtlasName(FileHandle fileHandle) {
@@ -175,15 +162,4 @@ public class ImportUtils {
}
return name;
}
public static 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;
}
}
@@ -0,0 +1,202 @@
package games.rednblack.editor.utils;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.TextureAtlasData;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.TextureAtlasData.Page;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.TextureAtlasData.Region;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
/** Unpacks a texture atlas into individual image files.
* @author Geert Konijnendijk
* @author Nathan Sweet
* @author Michael Bazos */
public class TextureUnpacker {
private static final String DEFAULT_OUTPUT_PATH = "output";
private static final int NINEPATCH_PADDING = 1;
private static final String OUTPUT_TYPE = "png";
private static final String HELP = "Usage: atlasFile [imageDir] [outputDir]";
private static final String ATLAS_FILE_EXTENSION = ".atlas";
private boolean quiet;
/** Checks the command line arguments for correctness.
* @return 0 If arguments are invalid, Number of arguments otherwise. */
private int parseArguments (String[] args) {
int numArgs = args.length;
// check if number of args is right
if (numArgs < 1) return 0;
// check if the input file's extension is right
boolean extension = args[0].substring(args[0].length() - ATLAS_FILE_EXTENSION.length()).equals(ATLAS_FILE_EXTENSION);
// check if the directory names are valid
boolean directory = true;
if (numArgs >= 2) directory &= checkDirectoryValidity(args[1]);
if (numArgs == 3) directory &= checkDirectoryValidity(args[2]);
return extension && directory ? numArgs : 0;
}
private boolean checkDirectoryValidity (String directory) {
File checkFile = new File(directory);
boolean path = true;
// try to get the canonical path, if this fails the path is not valid
try {
checkFile.getCanonicalPath();
} catch (Exception e) {
path = false;
}
return path;
}
/** Splits an atlas into seperate image and ninepatch files. */
public void splitAtlas (TextureAtlasData atlas, String prefix, String outputDir) {
// create the output directory if it did not exist yet
File outputDirFile = new File(outputDir);
if (!outputDirFile.exists()) {
outputDirFile.mkdirs();
if (!quiet) System.out.println(String.format("Creating directory: %s", outputDirFile.getPath()));
}
for (Page page : atlas.getPages()) {
// load the image file belonging to this page as a Buffered Image
File file = page.textureFile.file();
if (!file.exists()) throw new RuntimeException("Unable to find atlas image: " + file.getAbsolutePath());
BufferedImage img = null;
try {
img = ImageIO.read(file);
} catch (IOException e) {
printExceptionAndExit(e);
}
for (Region region : atlas.getRegions()) {
if (!quiet) System.out.println(String.format("Processing image for %s: x[%s] y[%s] w[%s] h[%s], rotate[%s]",
region.name, region.left, region.top, region.width, region.height, region.rotate));
// check if the page this region is in is currently loaded in a Buffered Image
if (region.page == page) {
BufferedImage splitImage = null;
String extension = null;
// check if the region is a ninepatch or a normal image and delegate accordingly
if (region.findValue("split") == null) {
splitImage = extractImage(img, region, outputDirFile, 0);
if (region.width != region.originalWidth || region.height != region.originalHeight) {
BufferedImage originalImg = new BufferedImage(region.originalWidth, region.originalHeight, img.getType());
Graphics2D g2 = originalImg.createGraphics();
g2.drawImage(splitImage, (int) region.offsetX, (int) (region.originalHeight - region.height - region.offsetY), null);
g2.dispose();
splitImage = originalImg;
}
extension = OUTPUT_TYPE;
} else {
splitImage = extractNinePatch(img, region, outputDirFile);
extension = String.format("9.%s", OUTPUT_TYPE);
}
// check if the parent directories of this image file exist and create them if not
File imgOutput;
if (prefix != null) {
imgOutput = new File(outputDirFile,
String.format("%s%s.%s", prefix, region.index == -1 ? region.name : region.name + "_" + region.index, extension));
} else {
imgOutput = new File(outputDirFile,
String.format("%s.%s", region.index == -1 ? region.name : region.name + "_" + region.index, extension));
}
File imgDir = imgOutput.getParentFile();
if (!imgDir.exists()) {
if (!quiet) System.out.printf("Creating directory: %s%n", imgDir.getPath());
imgDir.mkdirs();
}
// save the image
try {
ImageIO.write(splitImage, OUTPUT_TYPE, imgOutput);
} catch (Exception e) {
printExceptionAndExit(e);
}
}
}
}
}
/** Extract an image from a texture atlas.
* @param page The image file related to the page the region is in
* @param region The region to extract
* @param outputDirFile The output directory
* @param padding padding (in pixels) to apply to the image
* @return The extracted image */
private BufferedImage extractImage (BufferedImage page, Region region, File outputDirFile, int padding) {
BufferedImage splitImage = null;
// get the needed part of the page and rotate if needed
if (region.rotate) {
BufferedImage srcImage = page.getSubimage(region.left, region.top, region.height, region.width);
splitImage = new BufferedImage(region.width, region.height, page.getType());
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(90.0));
transform.translate(0, -region.width);
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
op.filter(srcImage, splitImage);
} else {
splitImage = page.getSubimage(region.left, region.top, region.width, region.height);
}
// draw the image to a bigger one if padding is needed
if (padding > 0) {
BufferedImage paddedImage = new BufferedImage(splitImage.getWidth() + padding * 2, splitImage.getHeight() + padding * 2,
page.getType());
Graphics2D g2 = paddedImage.createGraphics();
g2.drawImage(splitImage, padding, padding, null);
g2.dispose();
return paddedImage;
} else {
return splitImage;
}
}
/** Extract a ninepatch from a texture atlas, according to the android specification.
* @see <a href="http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch">ninepatch specification</a>
* @param page The image file related to the page the region is in
* @param region The region to extract */
private BufferedImage extractNinePatch (BufferedImage page, Region region, File outputDirFile) {
BufferedImage splitImage = extractImage(page, region, outputDirFile, NINEPATCH_PADDING);
Graphics2D g2 = splitImage.createGraphics();
g2.setColor(Color.BLACK);
// Draw the four lines to save the ninepatch's padding and splits
int[] splits = region.findValue("split");
int startX = splits[0] + NINEPATCH_PADDING;
int endX = region.width - splits[1] + NINEPATCH_PADDING - 1;
int startY = splits[2] + NINEPATCH_PADDING;
int endY = region.height - splits[3] + NINEPATCH_PADDING - 1;
if (endX >= startX) g2.drawLine(startX, 0, endX, 0);
if (endY >= startY) g2.drawLine(0, startY, 0, endY);
int[] pads = region.findValue("pad");
if (pads != null) {
int padStartX = pads[0] + NINEPATCH_PADDING;
int padEndX = region.width - pads[1] + NINEPATCH_PADDING - 1;
int padStartY = pads[2] + NINEPATCH_PADDING;
int padEndY = region.height - pads[3] + NINEPATCH_PADDING - 1;
g2.drawLine(padStartX, splitImage.getHeight() - 1, padEndX, splitImage.getHeight() - 1);
g2.drawLine(splitImage.getWidth() - 1, padStartY, splitImage.getWidth() - 1, padEndY);
}
g2.dispose();
return splitImage;
}
private void printExceptionAndExit (Exception e) {
e.printStackTrace();
System.exit(1);
}
public void setQuiet (boolean quiet) {
this.quiet = quiet;
}
}
@@ -57,6 +57,7 @@ public abstract class Asset implements IAsset {
executor.execute(() -> importAsset(files, progressHandler, skipRepack));
executor.execute(() -> {
progressHandler.progressChanged(100);
projectManager.saveCurrentProject();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
@@ -3,18 +3,20 @@ package games.rednblack.editor.utils.asset.impl;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import games.rednblack.editor.renderer.data.TexturePackVO;
import games.rednblack.editor.utils.ImportUtils;
import games.rednblack.editor.utils.asset.Asset;
import games.rednblack.h2d.common.ProgressHandler;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
public class AtlasAsset extends Asset {
@Override
protected int getType() {
//TODO Atlas not suported yet
return ImportUtils.TYPE_UNKNOWN;
//return ImportUtils.TYPE_TEXTURE_ATLAS;
return ImportUtils.TYPE_TEXTURE_ATLAS;
}
@Override
@@ -35,6 +37,34 @@ public class AtlasAsset extends Asset {
@Override
public void importAsset(Array<FileHandle> files, ProgressHandler progressHandler, boolean skipRepack) {
throw new GdxRuntimeException("Atlas not suported yet.");
try {
for (FileHandle fileHandle : new Array.ArrayIterator<>(files)) {
FileHandle tmpDir = new FileHandle(projectManager.getCurrentProjectPath() + File.separator + "tmp");
if (tmpDir.exists())
FileUtils.forceDelete(tmpDir.file());
FileUtils.forceMkdir(tmpDir.file());
ImportUtils.unpackAtlasIntoTmpFolder(fileHandle.file(), null, tmpDir.path());
Array<FileHandle> images = new Array<>(tmpDir.list());
projectManager.copyImageFilesForAllResolutionsIntoProject(images, true, progressHandler);
FileUtils.forceDelete(tmpDir.file());
TexturePackVO texturePackVO = projectManager.getCurrentProjectInfoVO().imagesPacks.get(fileHandle.nameWithoutExtension());
if (texturePackVO == null) {
texturePackVO = new TexturePackVO();
texturePackVO.name = fileHandle.nameWithoutExtension();
projectManager.getCurrentProjectInfoVO().imagesPacks.put(texturePackVO.name, texturePackVO);
}
for (FileHandle image : images) {
texturePackVO.regions.add(image.nameWithoutExtension().replace(".9", ""));
}
}
resolutionManager.rePackProjectImagesForAllResolutionsSync();
} catch (IOException e) {
e.printStackTrace();
progressHandler.progressFailed();
}
}
}
@@ -51,5 +51,9 @@ public class ImageAsset extends Asset {
ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME);
resolutionManager.rePackProjectImagesForAllResolutionsSync();
}
for (FileHandle handle : new Array.ArrayIterator<>(files)) {
projectManager.getCurrentProjectInfoVO().imagesPacks.get("main").regions.add(handle.nameWithoutExtension());
}
}
}
@@ -75,6 +75,10 @@ public class ParticleEffectAsset extends Asset {
}
if (images.size > 0) {
projectManager.copyImageFilesForAllResolutionsIntoProject(images, false, progressHandler);
for (FileHandle handle : new Array.ArrayIterator<>(images)) {
projectManager.getCurrentProjectInfoVO().imagesPacks.get("main").regions.add(handle.nameWithoutExtension());
}
}
if (!skipRepack) {
ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME);
@@ -1,6 +1,7 @@
package games.rednblack.editor.utils.asset.impl;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.utils.Array;
import com.kotcrab.vis.ui.util.dialog.Dialogs;
import games.rednblack.editor.proxy.ProjectManager;
@@ -53,17 +54,17 @@ public class SpineAsset extends Asset {
@Override
public void importAsset(Array<FileHandle> files, ProgressHandler progressHandler, boolean skipRepack) {
for (FileHandle handle : new Array.ArrayIterator<>(files)) {
File copiedFile = importExternalAnimationIntoProject(handle);
File copiedFile = importExternalAnimationIntoProject(handle, progressHandler);
if (copiedFile == null)
continue;
if (copiedFile.getName().toLowerCase().endsWith(".atlas")) {
resolutionManager.resizeSpineAnimationForAllResolutions(copiedFile, projectManager.getCurrentProjectInfoVO());
if (copiedFile.getName().toLowerCase().endsWith(".json")) {
resolutionManager.rePackProjectImagesForAllResolutionsSync();
}
}
}
private File importExternalAnimationIntoProject(FileHandle animationFileSource) {
private File importExternalAnimationIntoProject(FileHandle animationFileSource, ProgressHandler progressHandler) {
try {
String fileName = animationFileSource.name();
if (!HyperLap2DUtils.JSON_FILTER.accept(null, fileName)) {
@@ -85,11 +86,12 @@ public class SpineAsset extends Asset {
"\nCould not find '" + atlasFileSource.name() +"'.\nCheck if the file exists in the same directory.").padBottom(20).pack();
return null;
}
Array<File> imageFiles = ImportUtils.getAtlasPages(atlasFileSource);
for (File imageFile : new Array.ArrayIterator<>(imageFiles)) {
if (!imageFile.exists()) {
TextureAtlas.TextureAtlasData atlas = new TextureAtlas.TextureAtlasData(atlasFileSource, atlasFileSource.parent(), false);
for (TextureAtlas.TextureAtlasData.Page imageFile : new Array.ArrayIterator<>(atlas.getPages())) {
if (!imageFile.textureFile.exists()) {
Dialogs.showErrorDialog(Sandbox.getInstance().getUIStage(),
"\nCould not find " + imageFile.getName() + ".\nCheck if the file exists in the same directory.").padBottom(20).pack();
"\nCould not find " + imageFile.textureFile.name() + ".\nCheck if the file exists in the same directory.").padBottom(20).pack();
return null;
}
}
@@ -103,19 +105,22 @@ public class SpineAsset extends Asset {
FileUtils.forceMkdir(new File(targetPath));
File jsonFileTarget = new File(targetPath + File.separator + fileNameWithOutExt + ".json");
File atlasFileTarget = new File(targetPath + File.separator + fileNameWithOutExt + ".atlas");
FileUtils.copyFile(animationFileSource.file(), jsonFileTarget);
FileUtils.copyFile(atlasFileSource.file(), atlasFileTarget);
FileHandle tmpDir = new FileHandle(projectManager.getCurrentProjectPath() + File.separator + "tmp");
if (tmpDir.exists())
FileUtils.forceDelete(tmpDir.file());
FileUtils.forceMkdir(tmpDir.file());
ImportUtils.unpackAtlasIntoTmpFolder(atlasFileSource.file(), fileNameWithOutExt, tmpDir.path());
Array<FileHandle> images = new Array<>(tmpDir.list());
projectManager.copyImageFilesForAllResolutionsIntoProject(images, true, progressHandler);
FileUtils.forceDelete(tmpDir.file());
for (File imageFile : new Array.ArrayIterator<>(imageFiles)) {
FileHandle imgFileTarget = new FileHandle(targetPath + File.separator + imageFile.getName());
FileUtils.copyFile(imageFile, imgFileTarget.file());
for (TextureAtlas.TextureAtlasData.Region region : new Array.ArrayIterator<>(atlas.getRegions())) {
projectManager.getCurrentProjectInfoVO().animationsPacks.get("main").regions.add(fileNameWithOutExt+region.name);
}
return atlasFileTarget;
return jsonFileTarget;
}
} catch (IOException e) {
e.printStackTrace();
@@ -44,10 +44,9 @@ public class SpriteAnimationAtlasAsset extends Asset {
@Override
public void importAsset(Array<FileHandle> files, ProgressHandler progressHandler, boolean skipRepack) {
for (FileHandle fileHandle : new Array.ArrayIterator<>(files)) {
String newAnimName = null;
String newAnimName;
try {
Array<File> imgs = ImportUtils.getAtlasPages(fileHandle);
String fileNameWithoutExt = ImportUtils.getAtlasName(fileHandle);
String targetPath = projectManager.getCurrentProjectPath() + "/assets/orig/sprite-animations" + File.separator + fileNameWithoutExt;
@@ -55,9 +54,16 @@ public class SpriteAnimationAtlasAsset extends Asset {
if (targetDir.exists()) {
FileUtils.deleteDirectory(targetDir);
}
for (File img : imgs) {
FileUtils.copyFileToDirectory(img, targetDir);
}
FileHandle tmpDir = new FileHandle(projectManager.getCurrentProjectPath() + File.separator + "tmp");
if (tmpDir.exists())
FileUtils.forceDelete(tmpDir.file());
FileUtils.forceMkdir(tmpDir.file());
ImportUtils.unpackAtlasIntoTmpFolder(fileHandle.file(), null, tmpDir.path());
Array<FileHandle> images = new Array<>(tmpDir.list());
projectManager.copyImageFilesForAllResolutionsIntoProject(images, true, progressHandler);
FileUtils.forceDelete(tmpDir.file());
File atlasTargetPath = new File(targetPath + File.separator + fileNameWithoutExt + ".atlas");
FileUtils.copyFile(fileHandle.file(), atlasTargetPath);
newAnimName = fileNameWithoutExt;
@@ -68,7 +74,13 @@ public class SpriteAnimationAtlasAsset extends Asset {
}
if (newAnimName != null) {
resolutionManager.resizeSpriteAnimationForAllResolutions(newAnimName, projectManager.getCurrentProjectInfoVO());
TextureAtlas.TextureAtlasData atlas = new TextureAtlas.TextureAtlasData(fileHandle, fileHandle.parent(), false);
for (TextureAtlas.TextureAtlasData.Region region : new Array.ArrayIterator<>(atlas.getRegions())) {
projectManager.getCurrentProjectInfoVO().animationsPacks.get("main").regions.add(region.name);
}
resolutionManager.rePackProjectImagesForAllResolutionsSync();
}
}
}
@@ -1,10 +1,8 @@
package games.rednblack.editor.utils.asset.impl;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.tools.texturepacker.TexturePacker;
import com.badlogic.gdx.utils.Array;
import games.rednblack.editor.proxy.ProjectManager;
import games.rednblack.editor.utils.HyperLap2DUtils;
import games.rednblack.editor.utils.ImportUtils;
import games.rednblack.editor.utils.asset.Asset;
import games.rednblack.h2d.common.ProgressHandler;
@@ -49,7 +47,6 @@ public class SpriteAnimationSequenceAsset extends Asset {
String newAnimName;
String rawFileName = files.get(0).name();
TexturePacker texturePacker = new TexturePacker(projectManager.getTexturePackerSettings());
String fileNameWithoutExt = FilenameUtils.removeExtension(rawFileName);
String fileNameWithoutFrame = fileNameWithoutExt.replaceAll("\\d*$", "").replace("_", "");
@@ -61,15 +58,24 @@ public class SpriteAnimationSequenceAsset extends Asset {
}
String targetPath = projectManager.getCurrentProjectPath() + "/assets/orig/sprite-animations" + File.separator + fileNameWithoutFrame;
try {
FileUtils.writeStringToFile(new File(targetPath + File.separator + fileNameWithoutFrame + ".atlas"), fileNameWithoutFrame, "utf-8");
} catch (IOException e) {
e.printStackTrace();
progressHandler.progressFailed();
return;
}
String imagesPath = projectManager.getCurrentProjectPath() + File.separator + ProjectManager.IMAGE_DIR_PATH;
for (FileHandle file : new Array.ArrayIterator<>(files)) {
File src = file.file();
String destName;
if (noFileNameWithoutFrame) {
destName = targetPath + "Tmp" + File.separator + fileNameWithoutFrame + src.getName().replaceAll("[_](?=.*[_])", "");
destName = imagesPath + File.separator + fileNameWithoutFrame + src.getName().replaceAll("[_](?=.*[_])", "");
} else {
destName = targetPath + "Tmp" + File.separator + src.getName().replaceAll("[_](?=.*[_])", "");
destName = imagesPath + File.separator + src.getName().replaceAll("[_](?=.*[_])", "");
}
File dest = new File(destName);
@@ -82,42 +88,11 @@ public class SpriteAnimationSequenceAsset extends Asset {
}
}
FileHandle pngsDir = new FileHandle(targetPath + "Tmp");
for (FileHandle entry : pngsDir.list(HyperLap2DUtils.PNG_FILTER)) {
texturePacker.addImage(entry.file());
}
File targetDir = new File(targetPath);
if (targetDir.exists()) {
try {
FileUtils.deleteDirectory(targetDir);
} catch (IOException e) {
e.printStackTrace();
progressHandler.progressFailed();
return;
}
}
try {
texturePacker.pack(targetDir, fileNameWithoutFrame);
} catch (Exception e) {
progressHandler.progressFailed();
return;
}
//delete newly created directory and images
try {
FileUtils.deleteDirectory(pngsDir.file());
} catch (IOException e) {
e.printStackTrace();
progressHandler.progressFailed();
return;
}
newAnimName = fileNameWithoutFrame;
if (newAnimName != null) {
resolutionManager.resizeSpriteAnimationForAllResolutions(newAnimName, projectManager.getCurrentProjectInfoVO());
projectManager.getCurrentProjectInfoVO().animationsPacks.get("main").regions.add(newAnimName);
resolutionManager.rePackProjectImagesForAllResolutionsSync();
}
}
}
@@ -84,6 +84,10 @@ public class TalosVFXAsset extends Asset {
}
if (images.size > 0) {
projectManager.copyImageFilesForAllResolutionsIntoProject(images, false, progressHandler);
for (FileHandle handle : new Array.ArrayIterator<>(images)) {
projectManager.getCurrentProjectInfoVO().imagesPacks.get("main").regions.add(handle.nameWithoutExtension());
}
}
if (assetsRes.size > 0) {
for (FileHandle fileHandle : assetsRes) {
@@ -14,6 +14,8 @@ public class ResourcesMenu extends H2DMenu {
public static final String IMPORT_TO_LIBRARY = HyperLap2DMenuBar.prefix + ".IMPORT_TO_LIBRARY";
public static final String CREATE_PLACEHOLDER = HyperLap2DMenuBar.prefix + ".CREATE_PLACEHOLDER";
public static final String CREATE_NOISE = HyperLap2DMenuBar.prefix + ".CREATE_NOISE";
public static final String OPEN_IMAGES_PACK = HyperLap2DMenuBar.prefix + ".OPEN_IMAGES_PACK";
public static final String OPEN_ANIMATIONS_PACK = HyperLap2DMenuBar.prefix + ".OPEN_ANIMATIONS_PACK";
public ResourcesMenu() {
super("Resources");
@@ -21,10 +23,14 @@ public class ResourcesMenu extends H2DMenu {
MenuItem placeholders = new MenuItem("Create Placeholder...", new MenuItemListener(CREATE_PLACEHOLDER, null, RESOURCE_MENU));
MenuItem noise = new MenuItem("Create Perlin Noise...", new MenuItemListener(CREATE_NOISE, null, RESOURCE_MENU));
MenuItem repack = new MenuItem("Repack Assets", new MenuItemListener(MsgAPI.ACTION_REPACK, null, RESOURCE_MENU));
MenuItem imagesPack = new MenuItem("Images Atlases...", new MenuItemListener(OPEN_IMAGES_PACK, null, RESOURCE_MENU));
MenuItem animationsPack = new MenuItem("Animations Atlases...", new MenuItemListener(OPEN_ANIMATIONS_PACK, null, RESOURCE_MENU));
addItem(importToLibrary);
addSeparator();
addItem(repack);
addItem(imagesPack);
addItem(animationsPack);
addSeparator();
addItem(placeholders);
addItem(noise);
@@ -245,15 +245,6 @@ public class SelectionTool extends SimpleTool {
newX = MathUtils.floor(x / gridSize) * gridSize;
newY = MathUtils.floor(y / gridSize) * gridSize;
if (isShiftPressed()) {
if (directionVector.x == 0) {
newX = dragMouseStartPosition.x;
}
if (directionVector.y == 0) {
newY = dragMouseStartPosition.y;
}
}
// Selection rectangles should move and follow along
for (Entity itemInstance : sandbox.getSelector().getCurrentSelection()) {
transformComponent = ComponentRetriever.get(itemInstance, TransformComponent.class);
@@ -264,8 +255,16 @@ public class SelectionTool extends SimpleTool {
diff.x = MathUtils.floor(diff.x / gridSize) * gridSize;
diff.y = MathUtils.floor(diff.y / gridSize) * gridSize;
transformComponent.x = (newX - diff.x);
transformComponent.y = (newY - diff.y);
if (isShiftPressed()) {
if (directionVector.x == 0) {
transformComponent.y = (newY - diff.y);
} else if (directionVector.y == 0) {
transformComponent.x = (newX - diff.x);
}
} else {
transformComponent.x = (newX - diff.x);
transformComponent.y = (newY - diff.y);
}
//value.hide();
// pining UI to update current item properties tools
@@ -332,7 +331,7 @@ public class SelectionTool extends SimpleTool {
}
isDragging = false;
directionVector = null;
}
@Override
@@ -27,7 +27,9 @@ import com.badlogic.gdx.utils.Array;
import games.rednblack.editor.controller.commands.resource.DeleteImageResource;
import games.rednblack.editor.factory.ItemFactory;
import games.rednblack.editor.proxy.ProjectManager;
import games.rednblack.editor.proxy.ResourceManager;
import games.rednblack.editor.renderer.data.ProjectInfoVO;
import games.rednblack.editor.view.ui.box.resourcespanel.draggable.DraggableResource;
import games.rednblack.editor.view.ui.box.resourcespanel.draggable.box.ImageResource;
@@ -68,24 +70,31 @@ public class UIImagesTabMediator extends UIResourcesTabMediator<UIImagesTab> {
@Override
protected void initList(String searchText) {
ResourceManager resourceManager = facade.retrieveProxy(ResourceManager.NAME);
TextureAtlas atlas = resourceManager.getProjectAssetsList();
ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME);
ProjectInfoVO projectInfoVO = projectManager.getCurrentProjectInfoVO();
Array<DraggableResource> thumbnailBoxes = new Array<>();
Array<TextureAtlas.AtlasRegion> atlasRegions = atlas.getRegions();
for (TextureAtlas.AtlasRegion region : new Array.ArrayIterator<>(atlasRegions)) {
if(!region.name.contains(searchText))continue;
boolean is9patch = region.findValue("split") != null;
ImageResource imageResource = new ImageResource(region, new Color(1, 1, 1, 0.2f), new Color(1, 1, 1, 0.4f),
new Color(200f / 255f, 200f / 255f, 200f / 255f, 0.2f), new Color(255f / 255f, 94f / 255f, 0f / 255f, 1f), true);
DraggableResource draggableResource = new DraggableResource(imageResource);
if (is9patch) {
draggableResource.setFactoryFunction(ItemFactory.get()::create9Patch);
} else {
draggableResource.setFactoryFunction(ItemFactory.get()::createSimpleImage);
for (String atlasName : projectInfoVO.imagesPacks.keySet()) {
TextureAtlas atlas = resourceManager.getTextureAtlas(atlasName);
Array<TextureAtlas.AtlasRegion> atlasRegions = atlas.getRegions();
for (TextureAtlas.AtlasRegion region : new Array.ArrayIterator<>(atlasRegions)) {
if(!projectInfoVO.imagesPacks.get(atlasName).regions.contains(region.name)
|| !region.name.contains(searchText)) continue;
boolean is9patch = region.findValue("split") != null;
ImageResource imageResource = new ImageResource(region, new Color(1, 1, 1, 0.2f), new Color(1, 1, 1, 0.4f),
new Color(200f / 255f, 200f / 255f, 200f / 255f, 0.2f), new Color(255f / 255f, 94f / 255f, 0f / 255f, 1f), true);
DraggableResource draggableResource = new DraggableResource(imageResource);
if (is9patch) {
draggableResource.setFactoryFunction(ItemFactory.get()::create9Patch);
} else {
draggableResource.setFactoryFunction(ItemFactory.get()::createSimpleImage);
}
draggableResource.initDragDrop();
thumbnailBoxes.add(draggableResource);
}
draggableResource.initDragDrop();
thumbnailBoxes.add(draggableResource);
}
thumbnailBoxes.sort();
@@ -44,7 +44,7 @@ public class AboutDialog extends H2DDialog {
scrollPane.setFadeScrollBars(false);
mainTable.add(leftTable).top().padLeft(10).left();
mainTable.add(scrollPane).maxHeight(300).top().width(550).padLeft(28).expand().left();
mainTable.add(scrollPane).maxHeight(300).top().width(580).padLeft(28).expand().left();
leftTable.add(new VisImage(VisUI.getSkin().getDrawable("splash_logo"))).pad(5).row();
leftTable.add("HyperLap2D").padLeft(5).padRight(5).row();
@@ -0,0 +1,112 @@
package games.rednblack.editor.view.ui.dialog;
import games.rednblack.editor.HyperLap2DFacade;
import games.rednblack.editor.controller.commands.resource.DeleteImageResource;
import games.rednblack.editor.controller.commands.resource.DeleteSpineAnimation;
import games.rednblack.editor.controller.commands.resource.DeleteSpriteAnimation;
import games.rednblack.editor.proxy.ProjectManager;
import games.rednblack.editor.renderer.data.TexturePackVO;
import games.rednblack.editor.view.menu.ResourcesMenu;
import games.rednblack.editor.view.stage.Sandbox;
import games.rednblack.editor.view.stage.UIStage;
import org.puremvc.java.interfaces.INotification;
import org.puremvc.java.patterns.mediator.Mediator;
public class AnimationsPackDialogMediator extends Mediator<AtlasesPackDialog> {
private static final String TAG = AnimationsPackDialogMediator.class.getCanonicalName();
private static final String NAME = TAG;
private static final String NEW_IMAGES_PACK = "games.rednblack.editor.view.ui.dialog.AnimationsPackDialogMediator.NEW_IMAGES_PACK";
private static final String MOVE_REGION_TO_PACK = "games.rednblack.editor.view.ui.dialog.AnimationsPackDialogMediator.MOVE_REGION_TO_PACK";
private static final String UPDATE_CURRENT_LIST = "games.rednblack.editor.view.ui.dialog.AnimationsPackDialogMediator.UPDATE_CURRENT_LIST";
private static final String REMOVE_PACK = "games.rednblack.editor.view.ui.dialog.AnimationsPackDialogMediator.REMOVE_PACK";
public AnimationsPackDialogMediator() {
super(NAME, new AtlasesPackDialog("Animations Atlases", NEW_IMAGES_PACK, MOVE_REGION_TO_PACK, UPDATE_CURRENT_LIST, REMOVE_PACK));
}
@Override
public void onRegister() {
super.onRegister();
facade = HyperLap2DFacade.getInstance();
}
@Override
public String[] listNotificationInterests() {
return new String[]{
ResourcesMenu.OPEN_ANIMATIONS_PACK,
ProjectManager.PROJECT_OPENED,
NEW_IMAGES_PACK,
MOVE_REGION_TO_PACK,
UPDATE_CURRENT_LIST,
REMOVE_PACK,
ProjectManager.PROJECT_DATA_UPDATED,
DeleteImageResource.DONE,
DeleteSpineAnimation.DONE,
DeleteSpriteAnimation.DONE
};
}
@Override
public void handleNotification(INotification notification) {
Sandbox sandbox = Sandbox.getInstance();
UIStage uiStage = sandbox.getUIStage();
ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME);
String currentTab;
switch (notification.getName()) {
case ResourcesMenu.OPEN_ANIMATIONS_PACK:
viewComponent.show(uiStage);
break;
case ProjectManager.PROJECT_DATA_UPDATED:
case DeleteImageResource.DONE:
case DeleteSpineAnimation.DONE:
case DeleteSpriteAnimation.DONE:
viewComponent.updateMainPack(projectManager.currentProjectInfoVO.animationsPacks.get("main").regions);
currentTab = viewComponent.getSelectedTab();
if (currentTab != null)
viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.animationsPacks.get(currentTab).regions);
break;
case ProjectManager.PROJECT_OPENED:
viewComponent.initPacks(projectManager.currentProjectInfoVO.animationsPacks.keySet());
viewComponent.updateMainPack(projectManager.currentProjectInfoVO.animationsPacks.get("main").regions);
break;
case NEW_IMAGES_PACK:
TexturePackVO newVo = new TexturePackVO();
newVo.name = notification.getBody();
projectManager.currentProjectInfoVO.animationsPacks.put(newVo.name, newVo);
viewComponent.addNewPack(newVo.name);
projectManager.saveCurrentProject();
break;
case UPDATE_CURRENT_LIST:
currentTab = viewComponent.getSelectedTab();
System.out.println(currentTab);
if (currentTab != null)
viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.animationsPacks.get(currentTab).regions);
break;
case MOVE_REGION_TO_PACK:
String toPack = viewComponent.getMainSelected() != null ? viewComponent.getSelectedTab() : "main";
String fromPack = viewComponent.getMainSelected() == null ? viewComponent.getSelectedTab() : "main";
String region = viewComponent.getMainSelected() != null ? viewComponent.getMainSelected() : viewComponent.getCurrentSelected();
projectManager.currentProjectInfoVO.animationsPacks.get(fromPack).regions.remove(region);
projectManager.currentProjectInfoVO.animationsPacks.get(toPack).regions.add(region);
viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.animationsPacks.get(viewComponent.getSelectedTab()).regions);
viewComponent.updateMainPack(projectManager.currentProjectInfoVO.animationsPacks.get("main").regions);
projectManager.saveCurrentProject();
break;
case REMOVE_PACK:
String packToRemove = notification.getBody();
projectManager.currentProjectInfoVO.animationsPacks.get("main").regions.addAll(
projectManager.currentProjectInfoVO.animationsPacks.get(packToRemove).regions
);
projectManager.currentProjectInfoVO.animationsPacks.remove(packToRemove);
viewComponent.updateMainPack(projectManager.currentProjectInfoVO.animationsPacks.get("main").regions);
viewComponent.clearCurrentPack();
projectManager.saveCurrentProject();
break;
}
}
}
@@ -0,0 +1,280 @@
package games.rednblack.editor.view.ui.dialog;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.kotcrab.vis.ui.util.adapter.AbstractListAdapter;
import com.kotcrab.vis.ui.util.adapter.SimpleListAdapter;
import com.kotcrab.vis.ui.util.dialog.Dialogs;
import com.kotcrab.vis.ui.util.dialog.OptionDialogAdapter;
import com.kotcrab.vis.ui.widget.*;
import com.kotcrab.vis.ui.widget.tabbedpane.Tab;
import com.kotcrab.vis.ui.widget.tabbedpane.TabbedPane;
import com.kotcrab.vis.ui.widget.tabbedpane.TabbedPaneAdapter;
import games.rednblack.editor.HyperLap2DFacade;
import games.rednblack.editor.view.stage.Sandbox;
import games.rednblack.h2d.common.H2DDialog;
import games.rednblack.h2d.common.view.ui.StandardWidgetsFactory;
import games.rednblack.h2d.common.view.ui.listener.ScrollFocusListener;
import java.util.Set;
public class AtlasesPackDialog extends H2DDialog {
private final TabbedPane tabbedPane;
private final String addNewNotification;
private final String moveRegionNotification, updateCurrentNotification, removeNotification;
private final SimpleListAdapter<String> mainPackAdapter, currentPackAdapter;
private final VisTextButton insertButton, removeButton;
private final VisLabel currentSelectedPackLabel;
private final HyperLap2DFacade facade = HyperLap2DFacade.getInstance();
private final Array<String> mainList = new Array<>();
private final Array<String> currentList = new Array<>();
private String mainSelected = null, currentSelected = null;
public AtlasesPackDialog(String title, String add, String move, String updateList, String removeNotification) {
super(title);
addNewNotification = add;
moveRegionNotification = move;
updateCurrentNotification = updateList;
this.removeNotification = removeNotification;
addCloseButton();
getContentTable().top().left();
tabbedPane = new TabbedPane() {
@Override
public boolean remove(Tab tab, boolean ignoreTabDirty) {
Dialogs.showOptionDialog(Sandbox.getInstance().getUIStage(), "Remove Pack", "Are you sure to remove this pack?",
Dialogs.OptionDialogType.YES_NO_CANCEL, new OptionDialogAdapter() {
@Override
public void yes () {
facade.sendNotification(removeNotification, tab.getTabTitle());
packRemove(tab, ignoreTabDirty);
}
@Override
public void no () {
}
});
return false;
}
private boolean packRemove(Tab tab, boolean ignoreTabDirty) {
return super.remove(tab, ignoreTabDirty);
}
};
tabbedPane.addListener(new TabbedPaneAdapter() {
@Override
public void switchedTab(Tab tab) {
facade.sendNotification(updateCurrentNotification);
updateOpButtons();
currentSelectedPackLabel.setText(tab.getTabTitle());
}
});
VisTable addNewPackTable = new VisTable();
VisTextField newPackName = StandardWidgetsFactory.createTextField();
newPackName.setMessageText("Add new atlas pack");
VisTextButton newPackButton = StandardWidgetsFactory.createTextButton("Add");
newPackButton.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
if (!newPackName.getText().equals(""))
facade.sendNotification(addNewNotification, newPackName.getText());
newPackName.setText("");
}
});
addNewPackTable.add(newPackName).growX();
addNewPackTable.add(newPackButton).width(80);
mainPackAdapter = new SimpleListAdapter<>(mainList);
mainPackAdapter.setSelectionMode(AbstractListAdapter.SelectionMode.SINGLE);
mainPackAdapter.getSelectionManager().setProgrammaticChangeEvents(false);
currentPackAdapter = new SimpleListAdapter<>(currentList);
currentPackAdapter.setSelectionMode(AbstractListAdapter.SelectionMode.SINGLE);
currentPackAdapter.getSelectionManager().setProgrammaticChangeEvents(false);
ListView<String> mainPackList = new ListView<>(mainPackAdapter);
mainPackList.getScrollPane().addListener(new ScrollFocusListener());
ListView<String> currentPackList = new ListView<>(currentPackAdapter);
currentPackList.getScrollPane().addListener(new ScrollFocusListener());
mainPackList.setItemClickListener(this::selectMainItem);
currentPackList.setItemClickListener(this::selectCurrentItem);
getContentTable().add(addNewPackTable).growX().row();
getContentTable().add(tabbedPane.getTable()).height(30).growX().row();
insertButton = StandardWidgetsFactory.createTextButton("->");
insertButton.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
if (!insertButton.isDisabled())
facade.sendNotification(moveRegionNotification);
}
});
removeButton = StandardWidgetsFactory.createTextButton("<-");
removeButton.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
if (!removeButton.isDisabled())
facade.sendNotification(moveRegionNotification);
}
});
updateOpButtons();
VisTable opButtonsContainer = new VisTable();
VisTable opButtons = new VisTable();
opButtons.add(insertButton).width(80).row();
opButtons.add(removeButton).width(80).row();
opButtonsContainer.addSeparator(true);
opButtonsContainer.add(opButtons);
opButtonsContainer.addSeparator(true);
VisTable opTable = new VisTable();
opTable.add(new VisLabel("Main Pack", Align.center)).uniformX().growX();
opTable.add().width(80);
currentSelectedPackLabel = new VisLabel("Select Pack", Align.center);
opTable.add(currentSelectedPackLabel).uniformX().growX().row();
opTable.addSeparator().colspan(3);
opTable.add(mainPackList.getMainTable()).uniformX().grow();
opTable.add(opButtonsContainer).growY();
opTable.add(currentPackList.getMainTable()).uniformX().grow().row();
getContentTable().add(opTable).grow().row();
}
private void selectCurrentItem(String item) {
mainPackAdapter.getSelectionManager().deselectAll();
mainSelected = null;
currentSelected = item;
updateOpButtons();
}
private void selectMainItem(String item) {
currentPackAdapter.getSelectionManager().deselectAll();
currentSelected = null;
mainSelected = item;
updateOpButtons();
}
public void initPacks(Set<String> packs) {
tabbedPane.removeAll();
for (String name : packs) {
if (name.equals("main")) continue;
tabbedPane.add(new PackTab(name));
}
if (tabbedPane.getTabs().size > 0) tabbedPane.switchTab(0);
}
public void clearCurrentPack() {
currentList.clear();
currentPackAdapter.itemsChanged();
}
public void updateCurrentPack(Set<String> regions) {
String toSelect = null;
if (currentPackAdapter.getSelection().size > 0) {
String selected = currentPackAdapter.getSelection().get(0);
int nextIndex = currentList.indexOf(selected, false);
if (nextIndex + 1 < currentList.size)
toSelect = currentList.get(nextIndex + 1);
}
currentList.clear();
for (String item : regions)
currentList.addAll(item);
currentList.sort();
if (currentPackAdapter.getSelection().size > 0) {
selectCurrentItem(currentList.contains(toSelect, false) ? toSelect : null);
}
currentPackAdapter.itemsChanged();
if (toSelect != null && currentList.contains(toSelect, false)) {
currentPackAdapter.getSelectionManager().select(toSelect);
}
}
public void updateMainPack(Set<String> regions) {
String toSelect = null;
if (mainPackAdapter.getSelection().size > 0) {
String selected = mainPackAdapter.getSelection().get(0);
int nextIndex = mainList.indexOf(selected, false);
if (nextIndex + 1 < mainList.size)
toSelect = mainList.get(nextIndex + 1);
selectMainItem(toSelect);
}
mainList.clear();
for (String item : regions)
mainList.addAll(item);
mainList.sort();
mainPackAdapter.itemsChanged();
if (toSelect != null) {
mainPackAdapter.getSelectionManager().select(toSelect);
}
}
public void addNewPack(String name) {
tabbedPane.add(new PackTab(name));
pack();
}
public String getSelectedTab() {
if (tabbedPane.getActiveTab() == null)
return null;
return tabbedPane.getActiveTab().getTabTitle();
}
private void updateOpButtons() {
insertButton.setDisabled(tabbedPane.getActiveTab() == null || mainSelected == null);
removeButton.setDisabled(tabbedPane.getActiveTab() == null || currentSelected == null);
}
public String getCurrentSelected() {
return currentSelected;
}
public String getMainSelected() {
return mainSelected;
}
@Override
public float getPrefWidth() {
return Sandbox.getInstance().getUIStage().getWidth() * 0.5f;
}
@Override
public float getPrefHeight() {
return Sandbox.getInstance().getUIStage().getHeight() * 0.5f;
}
public static class PackTab extends Tab {
String name;
public PackTab (String name) {
super(false, true);
this.name = name;
}
@Override
public String getTabTitle() {
return name;
}
@Override
public Table getContentTable() {
return null;
}
}
}
@@ -0,0 +1,112 @@
package games.rednblack.editor.view.ui.dialog;
import games.rednblack.editor.HyperLap2DFacade;
import games.rednblack.editor.controller.commands.resource.DeleteImageResource;
import games.rednblack.editor.controller.commands.resource.DeleteSpineAnimation;
import games.rednblack.editor.controller.commands.resource.DeleteSpriteAnimation;
import games.rednblack.editor.proxy.ProjectManager;
import games.rednblack.editor.renderer.data.TexturePackVO;
import games.rednblack.editor.view.menu.ResourcesMenu;
import games.rednblack.editor.view.stage.Sandbox;
import games.rednblack.editor.view.stage.UIStage;
import org.puremvc.java.interfaces.INotification;
import org.puremvc.java.patterns.mediator.Mediator;
public class ImagesPackDialogMediator extends Mediator<AtlasesPackDialog> {
private static final String TAG = ImagesPackDialogMediator.class.getCanonicalName();
private static final String NAME = TAG;
private static final String NEW_IMAGES_PACK = "games.rednblack.editor.view.ui.dialog.ImagesPackDialogMediator.NEW_IMAGES_PACK";
private static final String MOVE_REGION_TO_PACK = "games.rednblack.editor.view.ui.dialog.ImagesPackDialogMediator.MOVE_REGION_TO_PACK";
private static final String UPDATE_CURRENT_LIST = "games.rednblack.editor.view.ui.dialog.ImagesPackDialogMediator.UPDATE_CURRENT_LIST";
private static final String REMOVE_PACK = "games.rednblack.editor.view.ui.dialog.ImagesPackDialogMediator.REMOVE_PACK";
public ImagesPackDialogMediator() {
super(NAME, new AtlasesPackDialog("Images Atlases", NEW_IMAGES_PACK, MOVE_REGION_TO_PACK, UPDATE_CURRENT_LIST, REMOVE_PACK));
}
@Override
public void onRegister() {
super.onRegister();
facade = HyperLap2DFacade.getInstance();
}
@Override
public String[] listNotificationInterests() {
return new String[]{
ResourcesMenu.OPEN_IMAGES_PACK,
ProjectManager.PROJECT_OPENED,
NEW_IMAGES_PACK,
MOVE_REGION_TO_PACK,
UPDATE_CURRENT_LIST,
REMOVE_PACK,
ProjectManager.PROJECT_DATA_UPDATED,
DeleteImageResource.DONE,
DeleteSpineAnimation.DONE,
DeleteSpriteAnimation.DONE
};
}
@Override
public void handleNotification(INotification notification) {
Sandbox sandbox = Sandbox.getInstance();
UIStage uiStage = sandbox.getUIStage();
ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME);
String currentTab;
switch (notification.getName()) {
case ResourcesMenu.OPEN_IMAGES_PACK:
viewComponent.show(uiStage);
break;
case ProjectManager.PROJECT_DATA_UPDATED:
case DeleteImageResource.DONE:
case DeleteSpineAnimation.DONE:
case DeleteSpriteAnimation.DONE:
viewComponent.updateMainPack(projectManager.currentProjectInfoVO.imagesPacks.get("main").regions);
currentTab = viewComponent.getSelectedTab();
if (currentTab != null)
viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.imagesPacks.get(currentTab).regions);
break;
case ProjectManager.PROJECT_OPENED:
viewComponent.initPacks(projectManager.currentProjectInfoVO.imagesPacks.keySet());
viewComponent.updateMainPack(projectManager.currentProjectInfoVO.imagesPacks.get("main").regions);
break;
case NEW_IMAGES_PACK:
TexturePackVO newVo = new TexturePackVO();
newVo.name = notification.getBody();
projectManager.currentProjectInfoVO.imagesPacks.put(newVo.name, newVo);
viewComponent.addNewPack(newVo.name);
projectManager.saveCurrentProject();
break;
case UPDATE_CURRENT_LIST:
currentTab = viewComponent.getSelectedTab();
if (currentTab != null)
viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.imagesPacks.get(currentTab).regions);
break;
case MOVE_REGION_TO_PACK:
String toPack = viewComponent.getMainSelected() != null ? viewComponent.getSelectedTab() : "main";
String fromPack = viewComponent.getMainSelected() == null ? viewComponent.getSelectedTab() : "main";
String region = viewComponent.getMainSelected() != null ? viewComponent.getMainSelected() : viewComponent.getCurrentSelected();
projectManager.currentProjectInfoVO.imagesPacks.get(fromPack).regions.remove(region);
projectManager.currentProjectInfoVO.imagesPacks.get(toPack).regions.add(region);
viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.imagesPacks.get(viewComponent.getSelectedTab()).regions);
viewComponent.updateMainPack(projectManager.currentProjectInfoVO.imagesPacks.get("main").regions);
projectManager.saveCurrentProject();
break;
case REMOVE_PACK:
String packToRemove = notification.getBody();
projectManager.currentProjectInfoVO.imagesPacks.get("main").regions.addAll(
projectManager.currentProjectInfoVO.imagesPacks.get(packToRemove).regions
);
projectManager.currentProjectInfoVO.imagesPacks.remove(packToRemove);
viewComponent.updateMainPack(projectManager.currentProjectInfoVO.imagesPacks.get("main").regions);
viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.imagesPacks.get(viewComponent.getSelectedTab()).regions);
viewComponent.clearCurrentPack();
projectManager.saveCurrentProject();
break;
}
}
}
@@ -19,6 +19,7 @@ import com.esotericsoftware.spine.attachments.Attachment;
import com.esotericsoftware.spine.attachments.MeshAttachment;
import com.esotericsoftware.spine.attachments.RegionAttachment;
import games.rednblack.editor.renderer.resources.IResourceRetriever;
import games.rednblack.h2d.extention.spine.ResourceRetrieverAttachmentLoader;
public class SpineActor extends Actor {
@@ -80,7 +81,7 @@ public class SpineActor extends Actor {
}
private void initSkeletonData() {
skeletonJson = new SkeletonJson(irr.getSkeletonAtlas(animationName));
skeletonJson = new SkeletonJson(new ResourceRetrieverAttachmentLoader(animationName, irr));
skeletonData = skeletonJson.readSkeletonData((irr.getSkeletonJSON(animationName)));
}
@@ -2,6 +2,7 @@ package games.rednblack.editor.view.ui.widget.actors;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor;
import games.rednblack.editor.renderer.resources.IResourceRetriever;
@@ -11,10 +12,10 @@ import games.rednblack.editor.renderer.resources.IResourceRetriever;
*/
public class SpriteAnimationActor extends Actor {
private String animationName;
private IResourceRetriever rm;
private final String animationName;
private final IResourceRetriever rm;
private Animation animation;
private final Animation<TextureAtlas.AtlasRegion> animation;
private float stateTime = 0;
private int fps;
@@ -24,17 +25,17 @@ public class SpriteAnimationActor extends Actor {
public SpriteAnimationActor(String animationName, IResourceRetriever rm) {
this.animationName = animationName;
this.rm = rm;
animation = new Animation(1/24f, rm.getSpriteAnimation(animationName).getRegions());
animation = new Animation<>(1/24f, rm.getSpriteAnimation(animationName));
animation.setPlayMode(Animation.PlayMode.LOOP);
TextureRegion region = (TextureRegion) animation.getKeyFrame(stateTime);
TextureRegion region = animation.getKeyFrame(stateTime);
setWidth(region.getRegionWidth());
setHeight(region.getRegionHeight());
}
@Override
public void draw(Batch batch, float parentAlpha) {
TextureRegion region = (TextureRegion) animation.getKeyFrame(stateTime);
TextureRegion region = animation.getKeyFrame(stateTime);
setWidth(region.getRegionWidth());
setHeight(region.getRegionHeight());