edit sprite (pls test i need alot, kinda buggy)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package funkin.backend.utils;
|
||||
|
||||
import flxanimate.data.AnimationData.AnimAtlas;
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import openfl.display.BitmapData;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
@@ -42,6 +43,8 @@ import haxe.xml.Access;
|
||||
import lime.utils.Assets;
|
||||
import openfl.geom.ColorTransform;
|
||||
import flixel.math.FlxPoint;
|
||||
import haxe.Constraints.IMap;
|
||||
import haxe.EnumTools.EnumValueTools;
|
||||
|
||||
using StringTools;
|
||||
|
||||
@@ -1168,6 +1171,113 @@ final class CoolUtil
|
||||
|
||||
return animsList;
|
||||
}
|
||||
|
||||
public static function getAnimsListFromAtlas(atlas:AnimAtlas):Array<String> {
|
||||
if (atlas == null) return [];
|
||||
|
||||
var animsList:Array<String> = [];
|
||||
if (atlas.AN.SN != null) animsList.push(atlas.AN.SN);
|
||||
if (atlas.SD != null)
|
||||
for (symbol in atlas.SD.S)
|
||||
if (symbol.SN != null) animsList.push(symbol.SN);
|
||||
|
||||
return animsList;
|
||||
}
|
||||
|
||||
// TODO: check this for bugs
|
||||
// Code from https://github.com/elnabo/equals/blob/master/src/equals/Equal.hx, (MIT License), but updated to work with haxe 4
|
||||
public static function deepEqual<T> (a:T, b:T) : Bool {
|
||||
if (a == b) { return true; } // if physical equality
|
||||
if (isNull(a) || isNull(b)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (Type.typeof(a)) {
|
||||
case TNull, TInt, TBool, TUnknown:
|
||||
return a == b;
|
||||
case TFloat:
|
||||
return Math.isNaN(cast a) && Math.isNaN(cast b); // only valid true result remaining
|
||||
case TFunction:
|
||||
return Reflect.compareMethods(a, b); // only physical equality can be tested for function
|
||||
case TEnum(_):
|
||||
if (EnumValueTools.getIndex(cast a) != EnumValueTools.getIndex(cast b)) {
|
||||
return false;
|
||||
}
|
||||
var a_args = EnumValueTools.getParameters(cast a);
|
||||
var b_args = EnumValueTools.getParameters(cast b);
|
||||
return deepEqual(a_args, b_args);
|
||||
case TClass(_):
|
||||
if ((a is String) && (b is String)) {
|
||||
return a == b;
|
||||
}
|
||||
if ((a is Array) && (b is Array)) {
|
||||
var a = cast(a, Array<Dynamic>);
|
||||
var b = cast(b, Array<Dynamic>);
|
||||
if (a.length != b.length) { return false; }
|
||||
for (i in 0...a.length) {
|
||||
if (!deepEqual(a[i], b[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((a is IMap) && (b is IMap)) {
|
||||
var a = cast(a, IMap<Dynamic, Dynamic>);
|
||||
var b = cast(b, IMap<Dynamic, Dynamic>);
|
||||
var a_keys = [ for (key in a.keys()) key ];
|
||||
var b_keys = [ for (key in b.keys()) key ];
|
||||
a_keys.sort(Reflect.compare);
|
||||
b_keys.sort(Reflect.compare);
|
||||
if (!deepEqual(a_keys, b_keys)) { return false; }
|
||||
for (key in a_keys) {
|
||||
if (!deepEqual(a.get(key), b.get(key))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((a is Date) && (b is Date)) {
|
||||
return cast(a, Date).getTime() == cast(b, Date).getTime();
|
||||
}
|
||||
|
||||
if ((a is haxe.io.Bytes) && (b is haxe.io.Bytes)) {
|
||||
return deepEqual(cast(a, haxe.io.Bytes).getData(), cast(b, haxe.io.Bytes).getData());
|
||||
}
|
||||
|
||||
case TObject:
|
||||
}
|
||||
|
||||
for (field in Reflect.fields(a)) {
|
||||
var pa = Reflect.field(a, field);
|
||||
var pb = Reflect.field(b, field);
|
||||
if (isFunction(pa)) {
|
||||
// ignore function as only physical equality can be tested, unless null
|
||||
if (isNull(pa) != isNull(pb)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!deepEqual(pa, pb)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline function isNull(a:Dynamic):Bool {
|
||||
return Type.enumEq(Type.typeof(a), TNull);
|
||||
}
|
||||
|
||||
static inline function isFunction(a:Dynamic):Bool {
|
||||
return Type.enumEq(Type.typeof(a), TFunction);
|
||||
}
|
||||
|
||||
public static inline function isMapEmpty<K, V>(map: Map<K, V>): Bool {
|
||||
return !map.keys().hasNext();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -264,18 +264,12 @@ class CharacterAnimButton extends UIButton {
|
||||
if (parent.character.animateAtlas != null)
|
||||
__refreshAnimation();
|
||||
else {
|
||||
trace(parent.character.animation._animations);
|
||||
var flxAnimation:FlxAnimation = __getFlxAnimation();
|
||||
trace(parent.character.animation._animations);
|
||||
flxAnimation.prefix = newAnim;
|
||||
|
||||
refreshFlxAnimationFrames(flxAnimation, animData);
|
||||
if (valid) {
|
||||
parent.buildAnimDisplay(anim, flxAnimation);
|
||||
animationDisplayBG.alpha = 1;
|
||||
} else {
|
||||
parent.removeAnimDisplay(anim);
|
||||
animationDisplayBG.alpha = 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent.character.getAnimName() == anim)
|
||||
@@ -349,9 +343,12 @@ class CharacterAnimButton extends UIButton {
|
||||
|
||||
flxAnimation.frames = frameIndices;
|
||||
} else {
|
||||
trace(flxAnimation.prefix);
|
||||
final animFrames:Array<FlxFrame> = new Array<FlxFrame>();
|
||||
parent.character.animation.findByPrefix(animFrames, flxAnimation.prefix);
|
||||
|
||||
trace(animFrames);
|
||||
|
||||
final frameIndices:Array<Int> = [];
|
||||
parent.character.animation.byPrefixHelper(frameIndices, animFrames, flxAnimation.prefix);
|
||||
|
||||
@@ -361,9 +358,17 @@ class CharacterAnimButton extends UIButton {
|
||||
if (flxAnimation.frames.length <= 0) invalidate();
|
||||
else validate();
|
||||
} catch (e) {
|
||||
trace('$e');
|
||||
trace('$e ${e.details}');
|
||||
invalidate();
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
parent.buildAnimDisplay(anim, flxAnimation);
|
||||
animationDisplayBG.alpha = 1;
|
||||
} else {
|
||||
parent.removeAnimDisplay(anim);
|
||||
animationDisplayBG.alpha = 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
public inline function refreshSymbolKeyFrames(symbol:FlxSymbolAnimation, animData:AnimData) @:privateAccess {
|
||||
@@ -450,13 +455,18 @@ class CharacterAnimButton extends UIButton {
|
||||
validate(false);
|
||||
|
||||
public inline function __getFlxAnimation():Null<FlxAnimation> @:privateAccess {
|
||||
if (parent.character.animation._animations[anim] == null)
|
||||
XMLUtil.addAnimToSprite(parent.character, data);
|
||||
if (!parent.character.animation._animations.exists(anim)) {
|
||||
final flxanim = new FlxAnimation(parent.character.animation, anim, [], data.fps, data.loop);
|
||||
flxanim.prefix = data.anim; // sobbing
|
||||
|
||||
parent.character.animation._animations.set(anim, flxanim);
|
||||
parent.character.animDatas.set(anim, data);
|
||||
}
|
||||
return parent.character.animation._animations[anim];
|
||||
}
|
||||
|
||||
public inline function __getAnimationSymbol():Null<FlxSymbolAnimation> @:privateAccess {
|
||||
if (parent.character.animateAtlas.anim.animsMap[anim] == null)
|
||||
if (!parent.character.animateAtlas.anim.animsMap.exists(anim))
|
||||
XMLUtil.addAnimToSprite(parent.character, data);
|
||||
return parent.character.animateAtlas.anim.animsMap[anim];
|
||||
}
|
||||
|
||||
@@ -305,7 +305,7 @@ class CharacterEditor extends UIState {
|
||||
uiGroup.add(animationText);
|
||||
|
||||
characterAnimsWindow = new CharacterAnimsWindow((FlxG.width-(500-16)-16), characterPropertiesWindow.y+224+16, character);
|
||||
uiGroup.add(characterAnimsWindow);
|
||||
uiGroup.add(characterPropertiesWindow.animsWindow = characterAnimsWindow);
|
||||
|
||||
add(uiGroup);
|
||||
|
||||
@@ -505,6 +505,7 @@ class CharacterEditor extends UIState {
|
||||
}
|
||||
|
||||
function _change_offset(x:Float, y:Float) {
|
||||
if (character.getAnimName() == null) return;
|
||||
_set_offset(
|
||||
character.animOffsets[character.getAnimName()].x - x,
|
||||
character.animOffsets[character.getAnimName()].y - y
|
||||
@@ -512,6 +513,8 @@ class CharacterEditor extends UIState {
|
||||
}
|
||||
|
||||
function _set_offset(x:Float, y:Float) {
|
||||
trace(character.getAnimName(), characterAnimsWindow.animButtons);
|
||||
if (character.getAnimName() == null) return;
|
||||
characterAnimsWindow.animButtons.get(character.getAnimName()).changeOffset(
|
||||
FlxMath.roundDecimal(x, 2), FlxMath.roundDecimal(y, 2)
|
||||
);
|
||||
|
||||
@@ -60,8 +60,10 @@ class CharacterGhost extends Character {
|
||||
|
||||
public function setAnimOffset(anim:String) {
|
||||
var daOffset:FlxPoint = animOffsets.get(anim);
|
||||
frameOffset.set(daOffset.x, daOffset.y);
|
||||
daOffset.putWeak();
|
||||
if (daOffset != null) {
|
||||
frameOffset.set(daOffset.x, daOffset.y);
|
||||
daOffset.putWeak();
|
||||
}
|
||||
|
||||
offset.set(globalOffset.x * (isPlayer != playerOffsets ? 1 : -1), -globalOffset.y);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package funkin.editors.character;
|
||||
|
||||
import haxe.io.Path;
|
||||
import funkin.editors.character.CharacterInfoScreen.CharacterExtraInfo;
|
||||
import funkin.game.Character;
|
||||
|
||||
class CharacterPropertiesWindow extends UISliceSprite {
|
||||
public var character:Character;
|
||||
public var animsWindow:CharacterAnimsWindow;
|
||||
|
||||
public var positionXStepper:UINumericStepper;
|
||||
public var positionYStepper:UINumericStepper;
|
||||
@@ -143,11 +145,43 @@ class CharacterPropertiesWindow extends UISliceSprite {
|
||||
}
|
||||
|
||||
public function editCharacterSpriteUI() {
|
||||
CharacterEditor.instance.openSubState(new CharacterSpriteScreen('characters/${character.sprite}', (sprite:String) -> {
|
||||
trace(sprite);
|
||||
CharacterEditor.instance.openSubState(new CharacterSpriteScreen('characters/${character.sprite}', (sprite:String, isAtlas:Bool) -> {
|
||||
changeSprite(sprite);
|
||||
}));
|
||||
}
|
||||
|
||||
public function changeSprite(sprite:String) @:privateAccess {
|
||||
var path:String = Paths.image('characters/$sprite');
|
||||
var noExt:String = Path.withoutExtension(path);
|
||||
|
||||
character.sprite = sprite;
|
||||
|
||||
if (Assets.exists('$noExt/Animation.json')) {
|
||||
character.atlasPath = noExt;
|
||||
character.animateAtlas.loadAtlas(noExt);
|
||||
|
||||
character.animateAtlas.anim.animsMap.clear();
|
||||
character.animateAtlas.anim.symbolDictionary.clear();
|
||||
|
||||
character.animateAtlas.anim.stop();
|
||||
} else {
|
||||
character.frames = Paths.getFrames(path, true);
|
||||
character.animation.reset();
|
||||
|
||||
animsWindow.displayWindowSprite.animation.reset();
|
||||
if (animsWindow.displayWindowGraphic != null)
|
||||
animsWindow.displayWindowGraphic.destroy();
|
||||
|
||||
animsWindow.displayWindowSprite.loadGraphicFromSprite(character);
|
||||
if (Assets.exists(Paths.image('characters/${character.sprite}')))
|
||||
animsWindow.displayWindowGraphic = FlxG.bitmap.add(Assets.getBitmapData(Paths.image('characters/${character.sprite}'), true, false));
|
||||
}
|
||||
|
||||
character.animDatas.clear();
|
||||
for (anim in animsWindow.buttons)
|
||||
anim.checkValid(); // Re-add all animations
|
||||
}
|
||||
|
||||
public function changeFlipX(newFlipX:Bool) @:privateAccess {
|
||||
character.flipX = character.isPlayer ? !newFlipX : newFlipX;
|
||||
character.__baseFlipped = character.flipX;
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
package funkin.editors.character;
|
||||
|
||||
import haxe.io.Bytes;
|
||||
import flixel.util.typeLimit.OneOfTwo;
|
||||
import flixel.text.FlxText.FlxTextFormat;
|
||||
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
||||
|
||||
class CharacterSpriteScreen extends UISubstateWindow {
|
||||
private var imagePath:String = null;
|
||||
private var onSave:String -> Void = null;
|
||||
private var onSave:(String, Bool) -> Void = null;
|
||||
|
||||
public var imageExplorer:UIFileExplorer;
|
||||
public var ogImageFiles:Map<String, OneOfTwo<String, Bytes>> = [];
|
||||
public var imageExplorer:UIImageExplorer;
|
||||
|
||||
public var saveButton:UIButton;
|
||||
public var closeButton:UIButton;
|
||||
|
||||
public function new(imagePath:String, ?onSave:String->Void) {
|
||||
public function new(imagePath:String, ?onSave:(String, Bool)->Void) {
|
||||
super();
|
||||
this.imagePath = imagePath;
|
||||
if (onSave != null) this.onSave = onSave;
|
||||
@@ -30,17 +33,23 @@ class CharacterSpriteScreen extends UISubstateWindow {
|
||||
|
||||
super.create();
|
||||
|
||||
imageExplorer = new UIImageExplorer(20, windowSpr.y + 30 + 16 + 20, imagePath, 320, 58, (_, _) -> {refreshWindowSize();});
|
||||
imageExplorer = new UIImageExplorer(20, windowSpr.y + 30 + 16 + 20, imagePath, 320, 58, (_, _) -> {onLoadImage();});
|
||||
add(imageExplorer);
|
||||
addLabelOn(imageExplorer, "Character Image File").applyMarkup(
|
||||
"Character Image File $* Required$",
|
||||
[new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]);
|
||||
|
||||
ogImageFiles = imageExplorer.imageFiles.copy();
|
||||
|
||||
saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20, windowSpr.y + windowSpr.bHeight - 20, "Save & Close", function() {
|
||||
close();
|
||||
imageExplorer.saveFiles('${Paths.getAssetsRoot()}/images/characters', () -> {
|
||||
onSave(imageExplorer.imageName, imageExplorer.isAtlas);
|
||||
close();
|
||||
});
|
||||
}, 125);
|
||||
saveButton.x -= saveButton.bWidth;
|
||||
saveButton.y -= saveButton.bHeight;
|
||||
saveButton.selectable = false;
|
||||
|
||||
closeButton = new UIButton(saveButton.x - 20, saveButton.y, "Cancel", function() {
|
||||
close();
|
||||
@@ -54,6 +63,14 @@ class CharacterSpriteScreen extends UISubstateWindow {
|
||||
refreshWindowSize();
|
||||
}
|
||||
|
||||
public function onLoadImage() {
|
||||
refreshWindowSize();
|
||||
|
||||
if (imageExplorer == null || imageExplorer.imageFiles == null) return;
|
||||
var filesSame = CoolUtil.deepEqual(ogImageFiles, imageExplorer.imageFiles);
|
||||
saveButton.selectable = !filesSame && !CoolUtil.isMapEmpty(imageExplorer.imageFiles) && (imageExplorer.animationList.length > 0);
|
||||
}
|
||||
|
||||
public function refreshWindowSize() {
|
||||
if (imageExplorer == null) return;
|
||||
windowSpr.bWidth = 20 + imageExplorer.bWidth + 20;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package funkin.editors.ui;
|
||||
|
||||
import flixel.util.typeLimit.OneOfTwo;
|
||||
import flixel.text.FlxText.FlxTextFormat;
|
||||
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
||||
import flxanimate.data.SpriteMapData.AnimateAtlas;
|
||||
@@ -15,6 +16,8 @@ using funkin.backend.utils.BitmapUtil;
|
||||
|
||||
// TODO: make this limited if on web
|
||||
class UIImageExplorer extends UIFileExplorer {
|
||||
private var allowAtlases:Bool = true;
|
||||
|
||||
public function new(x:Float, y:Float, image:String, ?w:Int, ?h:Int, ?onFile:(String, Bytes)->Void) {
|
||||
super(x, y, w, h, "png, jpg", function (filePath, file) {
|
||||
if (filePath != null && file != null) uploadImage(filePath, file);
|
||||
@@ -33,32 +36,37 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
loadFile(fullImagePath);
|
||||
}
|
||||
|
||||
private var allowAtlases:Bool = true;
|
||||
|
||||
public var fileText:UIText;
|
||||
public var isAtlas:Bool = false;
|
||||
|
||||
static var ANIMATE_ATLAS_REGEX = ~/^(?:Animation\.json|spritemap(?:\d+)?\.json)$/i; // no .zip atlases tho
|
||||
static var SPRITEMAP_JSON_REGEX = ~/^(?:spritemap(?:\d+)?\.json)$/i;
|
||||
static var SPRITEMAP_PNG_REGEX = ~/^(?:spritemap(?:\d+)?\.png)$/i;
|
||||
|
||||
public var imageName:String = null;
|
||||
public var imageFiles:Map<String, OneOfTwo<String, Bytes>> = [];
|
||||
public var animationList:Array<String> = [];
|
||||
|
||||
public var fileText:UIText;
|
||||
|
||||
public function uploadImage(filePath:String, file:Bytes) {
|
||||
__resetData();
|
||||
|
||||
var imagePath:Dynamic = Path.normalize(filePath);
|
||||
|
||||
var directoryPath:String = Path.directory(imagePath);
|
||||
var fileName:String = Path.withoutDirectory(imagePath).toLowerCase();
|
||||
var files:Array<String> = [];
|
||||
|
||||
var isAtlas:Bool = false;
|
||||
// CHECK ATLAS
|
||||
if(allowAtlases && ANIMATE_ATLAS_REGEX.match(fileName)) {
|
||||
// check if directory has the other files
|
||||
files = FileSystem.readDirectory(directoryPath);
|
||||
var hasAnimationJson:Bool = false;
|
||||
var hasSpritemapJson:Bool = false;
|
||||
for(file in files) {
|
||||
file = file.toLowerCase();
|
||||
if(file == "animation.json")
|
||||
if(file == "Animation.json")
|
||||
hasAnimationJson = true;
|
||||
else if(SPRITEMAP_JSON_REGEX.match(file))
|
||||
else if(SPRITEMAP_JSON_REGEX.match(file.toLowerCase()))
|
||||
hasSpritemapJson = true;
|
||||
|
||||
if(hasAnimationJson && hasSpritemapJson) {
|
||||
@@ -77,7 +85,7 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
var json:AnimateAtlas = Json.parse(content);
|
||||
if(json.meta.image.toLowerCase() == fileName.toLowerCase())
|
||||
foundSpritemapJson = true;
|
||||
} else if(file.toLowerCase() == "animation.json")
|
||||
} else if(file == "Animation.json")
|
||||
hasAnimationJson = true;
|
||||
|
||||
if(hasAnimationJson && foundSpritemapJson) {
|
||||
@@ -87,6 +95,7 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
}
|
||||
}
|
||||
|
||||
// IF ATLAS FIND SPRITMAPS
|
||||
var spritemaps:Array<String> = [];
|
||||
var spritemapImages:Array<String> = [];
|
||||
if(isAtlas) {
|
||||
@@ -96,7 +105,6 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
spritemaps.push(file);
|
||||
|
||||
spritemaps.sort(Reflect.compare);
|
||||
|
||||
for(spritemap in spritemaps) {
|
||||
var content:String = CoolUtil.removeBOM(File.getContent(Path.join([directoryPath, spritemap])));
|
||||
var json:AnimateAtlas = Json.parse(content);
|
||||
@@ -115,14 +123,31 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
isAtlas = false;
|
||||
}
|
||||
|
||||
var dataPathExt:String = !isAtlas ? CoolUtil.imageHasFrameData(imagePath) : null;
|
||||
var animationList:Array<String> = [];
|
||||
// GATHER ANIMATIONS/DATA FILES!!!
|
||||
if (isAtlas) {
|
||||
var dataPath:String = '$directoryPath/Animation.json'.replace('/', '\\');
|
||||
|
||||
if (dataPathExt != null)
|
||||
animationList = CoolUtil.getAnimsListFromFrames(CoolUtil.loadFramesFromData(File.getContent(Path.withExtension(imagePath, dataPathExt)), dataPathExt), dataPathExt);
|
||||
if (FileSystem.exists(dataPath)) {
|
||||
var dataPathFile:String = File.getContent(dataPath);
|
||||
animationList = CoolUtil.getAnimsListFromAtlas(cast haxe.Json.parse(dataPathFile));
|
||||
|
||||
var size = 0;
|
||||
var image = null;
|
||||
imageFiles.set(Path.withoutDirectory(dataPath), dataPathFile);
|
||||
}
|
||||
} else {
|
||||
var dataPathExt:String = CoolUtil.imageHasFrameData(imagePath);
|
||||
var dataPath:String = Path.withExtension(imagePath, dataPathExt);
|
||||
var dataPathFile:String = !isAtlas ? File.getContent(dataPath) : null;
|
||||
|
||||
if (dataPathExt != null) {
|
||||
animationList = CoolUtil.getAnimsListFromFrames(CoolUtil.loadFramesFromData(dataPathFile, dataPathExt), dataPathExt);
|
||||
|
||||
imageFiles.set(Path.withoutDirectory(dataPath), dataPathFile);
|
||||
}
|
||||
}
|
||||
|
||||
// GATHER INFO!!!
|
||||
var size:Float = 0;
|
||||
var image:BitmapData = null;
|
||||
if (isAtlas && spritemapImages.length > 0) {
|
||||
var spritemapPath:String = Path.join([directoryPath, spritemapImages[0]]);
|
||||
|
||||
@@ -132,25 +157,31 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
|
||||
for(spritemap in spritemapImages) {
|
||||
var spritemapPath:String = Path.join([directoryPath, spritemap]);
|
||||
|
||||
var info = FileSystem.stat(spritemapPath);
|
||||
size += info.size;
|
||||
|
||||
spritemapPath = spritemapPath.replace('/', '\\');
|
||||
imageFiles.set(Path.withoutDirectory(spritemapPath), sys.io.File.getBytes(spritemapPath));
|
||||
}
|
||||
|
||||
image = BitmapData.fromFile(spritemapPath).crop();
|
||||
file = cast sys.io.File.getBytes(filePath = spritemapPath);
|
||||
image = BitmapData.fromBytes(file).crop();
|
||||
|
||||
} else {
|
||||
trace("Loading image");
|
||||
size = file.length;
|
||||
image = BitmapData.fromBytes(file).crop();
|
||||
|
||||
imageFiles.set(Path.withoutDirectory(imagePath), file);
|
||||
}
|
||||
|
||||
// DISPLAY IMAGE!!
|
||||
uiElement = new FlxSprite().loadGraphic(image);
|
||||
|
||||
var imageScale:Float = 1;
|
||||
if (uiElement.width < 300 || uiElement.height < 200)
|
||||
imageScale = Math.max(300/uiElement.width, 200/uiElement.height);
|
||||
else if (uiElement.width > 700 || uiElement.height > 500)
|
||||
imageScale = Math.min(700/uiElement.width, 500/uiElement.height);
|
||||
|
||||
uiElement.scale.set(imageScale, imageScale);
|
||||
uiElement.updateHitbox();
|
||||
|
||||
@@ -160,31 +191,25 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
uiElement.antialiasing = true;
|
||||
members.push(uiElement);
|
||||
|
||||
// GENERATE TEXT!!!
|
||||
imagePath = new Path(imagePath);
|
||||
imageName = isAtlas ? Path.withoutDirectory(directoryPath) : ${imagePath.file};
|
||||
|
||||
var message = new StringBuf();
|
||||
if (isAtlas) message.add('${imageName}/');
|
||||
message.add('${imagePath.file}.${imagePath.ext}');
|
||||
|
||||
message.add(' (${CoolUtil.getSizeString(size)}');
|
||||
|
||||
if(!isAtlas) {
|
||||
if (animationList.length > 0) {
|
||||
if(animationList.length == 1)
|
||||
message.add(', ${animationList.length} Animation Found');
|
||||
else
|
||||
message.add(', ${animationList.length} Animations Found');
|
||||
}
|
||||
else
|
||||
message.add(', #NO Animations Found#');
|
||||
} else {
|
||||
if(spritemaps.length == 1)
|
||||
message.add(', ${spritemaps.length} Spritemap Found');
|
||||
else
|
||||
message.add(', ${spritemaps.length} Spritemaps Found');
|
||||
if (animationList.length > 0) {
|
||||
if(animationList.length == 1) message.add(', ${animationList.length} ${isAtlas ? "Symbol" : "Animation"} Found');
|
||||
else message.add(', ${animationList.length} ${isAtlas ? "Symbol" : "Animation"}s Found');
|
||||
} else message.add(', #NO ${isAtlas ? "Symbol" : "Animation"}s Found#');
|
||||
|
||||
if (isAtlas) {
|
||||
if(spritemaps.length == 1) message.add(', ${spritemaps.length} Spritemap Found');
|
||||
else message.add(', ${spritemaps.length} Spritemaps Found');
|
||||
}
|
||||
|
||||
message.add(')');
|
||||
|
||||
message.add(isAtlas ? " - Atlas" : " - Spritemap");
|
||||
|
||||
fileText = new UIText(x+20, y+16, bWidth-20-deleteButton.bWidth-16, "");
|
||||
@@ -196,17 +221,54 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
|
||||
deleteIcon.x = deleteButton.x + deleteButton.bWidth/2 - 8;
|
||||
deleteIcon.y = deleteButton.y + deleteButton.bHeight/2 - 8;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
var normalFilePath:String = Path.normalize(filePath);
|
||||
var gamePath:String = Path.normalize(Sys.getCwd());
|
||||
public function saveFiles(directory:String, ?onFinishSaving:Void->Void, ?checkExisting:Bool = true) {
|
||||
if (isAtlas) directory += '/$imageName';
|
||||
|
||||
if (normalFilePath.contains(gamePath))
|
||||
normalFilePath = normalFilePath.replace(gamePath, ".");
|
||||
*/
|
||||
var alreadlyExistingFiles:Array<String> = [];
|
||||
for (name => file in imageFiles)
|
||||
if (FileSystem.exists('$directory/$name'))
|
||||
alreadlyExistingFiles.push('$directory/$name');
|
||||
|
||||
function deleteExistingFiles() {
|
||||
for (file in alreadlyExistingFiles)
|
||||
FileSystem.deleteFile(file);
|
||||
alreadlyExistingFiles = [];
|
||||
}
|
||||
|
||||
function acuttalySaveFiles() {
|
||||
for (name => file in imageFiles)
|
||||
if (!alreadlyExistingFiles.contains('$directory/$name')) {
|
||||
CoolUtil.safeSaveFile('$directory/$name', file);
|
||||
trace('SAVED: $directory/$name');
|
||||
}
|
||||
|
||||
if (onFinishSaving != null) onFinishSaving();
|
||||
}
|
||||
|
||||
if (alreadlyExistingFiles.length > 0) {
|
||||
(FlxG.state.subState != null ? FlxG.state.subState : FlxG.state).openSubState(new UIWarningSubstate("Alreadly Existing Files!!!",
|
||||
"The following files alreadly exist: \n\n" + alreadlyExistingFiles.join('\n') + "\n\nIMPORTANT: OVERRIDING CAN NOT BE UNDONE!!!!!!!!",
|
||||
[ {
|
||||
label: "Override Files",
|
||||
color: 0xFFFF0000,
|
||||
onClick: (_) -> {
|
||||
deleteExistingFiles();
|
||||
acuttalySaveFiles();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "Use Existing",
|
||||
onClick: (_) -> {if (onFinishSaving != null) onFinishSaving();}
|
||||
}
|
||||
], false));
|
||||
} else acuttalySaveFiles();
|
||||
}
|
||||
|
||||
public override function removeFile() {
|
||||
__resetData();
|
||||
bWidth = 320; bHeight = 58;
|
||||
|
||||
members.remove(fileText);
|
||||
@@ -214,4 +276,8 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
|
||||
super.removeFile();
|
||||
}
|
||||
|
||||
@:noCompletion inline function __resetData() {
|
||||
imageFiles.clear(); isAtlas = false; animationList = [];
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,16 @@ class UIWarningSubstate extends MusicBeatSubstate {
|
||||
warnCam.zoom = 0.1;
|
||||
FlxG.cameras.add(warnCam, false);
|
||||
|
||||
|
||||
var spr = new UISliceSprite(0, 0, CoolUtil.maxInt(560, 30 + (170 * buttons.length)), 232, 'editors/ui/${isError ? "normal" : "grayscale"}-popup');
|
||||
|
||||
var sprIcon:FlxSprite = new FlxSprite(spr.x + 18, spr.y + 28 + 26).loadGraphic(Paths.image('editors/warnings/${isError ? "error" : "warning"}'));
|
||||
sprIcon.scale.set(1.4, 1.4);
|
||||
sprIcon.updateHitbox();
|
||||
|
||||
messageSpr = new UIText(0,0, spr.bWidth - 100 - (26 * 2), message);
|
||||
spr.bHeight = Std.int(232 + Math.abs(Math.min(sprIcon.height-messageSpr.height, 0)));
|
||||
|
||||
spr.x = (FlxG.width - spr.bWidth) / 2;
|
||||
spr.y = (FlxG.height - spr.bHeight) / 2;
|
||||
spr.color = isError ? 0xFFFF0000 : 0xFFFFFF00;
|
||||
@@ -86,7 +95,9 @@ class UIWarningSubstate extends MusicBeatSubstate {
|
||||
sprIcon.antialiasing = true;
|
||||
add(sprIcon);
|
||||
|
||||
add(messageSpr = new UIText(sprIcon.x + 70 + 16 + 20, sprIcon.y + 16, spr.bWidth - 100 - (26 * 2), message));
|
||||
messageSpr.x = sprIcon.x + 70 + 16 + 20;
|
||||
messageSpr.y = sprIcon.y + 16;
|
||||
add(messageSpr);
|
||||
|
||||
var xPos = (FlxG.width - (30 + (170 * buttons.length))) / 2;
|
||||
for(k=>b in buttons) {
|
||||
|
||||
Reference in New Issue
Block a user