Merge branch 'stage-editor' of https://github.com/NeeEoo/CodenameEngine-Dev into stage-editor

This commit is contained in:
SrtHero278
2024-04-16 06:59:46 -07:00
4 changed files with 282 additions and 75 deletions
+2
View File
@@ -154,6 +154,8 @@ class XMLUtil {
spr.skipNegativeBeats = node.att.playOnCountdown == "true";
if (node.has.beatInterval)
spr.beatInterval = Std.parseInt(node.att.beatInterval);
if (node.has.interval)
spr.beatInterval = Std.parseInt(node.att.interval);
if (node.has.beatOffset)
spr.beatOffset = Std.parseInt(node.att.beatOffset);
+211 -38
View File
@@ -100,6 +100,42 @@ class StageEditor extends UIState {
}
]
},
/*{
label: "Edit",
childs: [
{
label: "Undo",
keybind: [CONTROL, Z],
onSelect: _edit_undo,
},
{
label: "Redo",
keybind: [CONTROL, SHIFT, Z],
onSelect: _edit_redo,
},
null,
]
},*/
{
label: "Select",
childs: [
{
label: "All",
keybind: [CONTROL, A],
onSelect: (_) -> _select_all(_),
},
{
label: "Deselect",
keybind: [CONTROL, D],
onSelect: (_) -> _select_deselect(_),
},
{
label: "Inverse",
keybind: [CONTROL, SHIFT, I],
onSelect: (_) -> _select_inverse(_),
},
]
},
{
label: "View",
childs: [
@@ -220,6 +256,7 @@ class StageEditor extends UIState {
char.alpha = 0.5;
char.extra.set(exID("node"), node);
char.extra.set(exID("pos"), charPos);
charPos.extra.set(exID("node"), node);
charPos.extra.set(exID("char"), char);
chars.push(char);
}
@@ -233,7 +270,7 @@ class StageEditor extends UIState {
for(char in chars) {
var charPos = char.extra.get(exID("pos"));
var node = char.extra.get(exID("node"));
var node:Access = cast char.extra.get(exID("node"));
stage.applyCharStuff(char, charPos.name, 0);
charMap[charPos.name] = char;
@@ -401,9 +438,12 @@ class StageEditor extends UIState {
}
}*/
for(sprite in selection) {
if(sprite is FunkinSprite) {
handleSelection(cast sprite);
// TODO: make this work with multiple selections
if(selection.length == 1) {
for(sprite in selection) {
if(sprite is FunkinSprite) {
handleSelection(cast sprite);
}
}
}
@@ -430,25 +470,6 @@ class StageEditor extends UIState {
SaveWarning.showWarning = undos.unsaved;
}
public function selectSprite(_sprite:FunkinSprite) {
selection = new Selection([]);
var sprites = stageSpritesWindow.buttons.members.map((o) -> o.getSprite()).filter((o) -> o != null);// && o.animateAtlas == null);
for(sprite in sprites) {
if(sprite is FunkinSprite) {
var sprite:FunkinSprite = cast sprite;
sprite.extra.set(exID("selected"), false);
sprite.extra.get(exID("button")).selected = false;
}
}
if(_sprite is FunkinSprite) {
var sprite:FunkinSprite = cast _sprite;
sprite.extra.set(exID("selected"), true);
sprite.extra.get(exID("button")).selected = true;
selection = new Selection([sprite]);
Logs.trace("Selected " + sprite.name);
}
}
// TOP MENU OPTIONS
#if REGION
function _file_exit(_) {
@@ -478,26 +499,119 @@ class StageEditor extends UIState {
undos.save();
}
function saveToXml(xml:Xml, name:String, value:Dynamic, ?defaultValue:Dynamic) {
if(value == null || value == defaultValue) return xml;
xml.set(name, Std.string(value));
return xml;
}
function savePointToXml(xml:Xml, name:String, point:FlxPoint, ?defaultValueX:Float, ?defaultValueY:Float) {
if (point == null) return xml;
if(point.x == point.y) {
saveToXml(xml, name, point.x, defaultValueX);
} else {
saveToXml(xml, name + "x", point.x, defaultValueX);
saveToXml(xml, name + "y", point.y, defaultValueY);
}
return xml;
}
function getBoolOfNode(node:Access, name:String) {
var xml:Xml = cast node;
return xml.exists(name) && xml.get(name) == "true";
}
function buildStage():String {
/*if (character.isPlayer != character.playerOffsets) {
character.switchOffset('singLEFT', 'singRIGHT');
character.switchOffset('singLEFTmiss', 'singRIGHTmiss');
var xml = Xml.createElement("stage");
saveToXml(xml, "zoom", stage.defaultZoom, 1.05);
saveToXml(xml, "name", stage.stageName);
saveToXml(xml, "folder", stage.spritesParentFolder);
saveToXml(xml, "startCamPosX", stage.startCam.x, 0);
saveToXml(xml, "startCamPosY", stage.startCam.y, 0);
for(sprite in getSprites()) {
var button:StageElementButton = sprite.extra.get(exID("button"));
if(button is StageSolidButton) {
var button:StageSolidButton = cast button;
var sprite:FunkinSprite = button.getSprite();
var node:Access = cast sprite.extra.get(exID("node"));
Logs.trace("SOLID / BOX isnt implemented yet!");
} else if(button is StageSpriteButton) {
var button:StageSpriteButton = cast button;
var sprite:FunkinSprite = button.getSprite();
var node:Access = cast sprite.extra.get(exID("node"));
var spriteXML = Xml.createElement("sprite");
saveToXml(spriteXML, "name", sprite.name);
saveToXml(spriteXML, "x", sprite.x, 0);
saveToXml(spriteXML, "y", sprite.y, 0);
saveToXml(spriteXML, "sprite", sprite.extra.get(exID("imageFile")));
savePointToXml(spriteXML, "scale", sprite.scale, 1, 1);
savePointToXml(spriteXML, "scroll", sprite.scrollFactor, 0, 0);
saveToXml(spriteXML, "skewx", sprite.skew.x, 0);
saveToXml(spriteXML, "skewy", sprite.skew.y, 0);
saveToXml(spriteXML, "alpha", sprite.alpha, 1);
//saveToXml(spriteXML, "graphicSize", sprite.width, sprite.width);
//saveToXml(spriteXML, "graphicSizex", sprite.height, sprite.height);
//saveToXml(spriteXML, "graphicSizey", sprite.height, sprite.height);
saveToXml(spriteXML, "zoomfactor", sprite.zoomFactor, 1);
saveToXml(spriteXML, "updateHitbox", getBoolOfNode(node, "updateHitbox"), false);
saveToXml(spriteXML, "antialiasing", sprite.antialiasing, true);
//saveToXml(spriteXML, "width", sprite.width);
//saveToXml(spriteXML, "height", sprite.height);
saveToXml(spriteXML, "playOnCountdown", getBoolOfNode(node, "playOnCountdown"), false);
saveToXml(spriteXML, "interval", node.getAtt("beatInterval"), 2);
saveToXml(spriteXML, "interval", node.getAtt("interval"), 2);
saveToXml(spriteXML, "beatOffset", node.getAtt("beatOffset"), 0);
saveToXml(spriteXML, "type", sprite.spriteAnimType, LOOP);
saveToXml(spriteXML, "color", sprite.color.toWebString(), "#FFFFFF");
//saveToXml(spriteXML, "flipX", sprite.flipX, false);
xml.addChild(spriteXML);
} else if(button is StageCharacterButton) {
var button:StageCharacterButton = cast button;
var charPos:StageCharPos = button.charPos;
var char:Character = cast charPos.extra.get(exID("char"));
var node:Access = cast charPos.extra.get(exID("node"));
var nodeName = switch(charPos.name) {
case "boyfriend": "boyfriend";
case "dad": "dad";
case "girlfriend": "girlfriend";
default: "character";
}
var defaultPos = Stage.getDefaultPos(charPos.name);
var charXML:Xml = Xml.createElement(nodeName);
if(nodeName == "character")
saveToXml(charXML, "name", char.curCharacter);
saveToXml(charXML, "x", charPos.x, defaultPos.x);
saveToXml(charXML, "y", charPos.y, defaultPos.y);
saveToXml(charXML, "camxoffset", charPos.camxoffset, 0);
saveToXml(charXML, "camyoffset", charPos.camyoffset, 0);
saveToXml(charXML, "skewx", charPos.skewX, 0);
saveToXml(charXML, "skewy", charPos.skewY, 0);
saveToXml(charXML, "spacingx", charPos.charSpacingX, 20);
saveToXml(charXML, "spacingy", charPos.charSpacingY, 0);
saveToXml(charXML, "alpha", charPos.alpha, 1);
saveToXml(charXML, "flipX", charPos.flipX, defaultPos.flip);
savePointToXml(charXML, "scroll", charPos.scrollFactor, defaultPos.scroll, defaultPos.scroll);
savePointToXml(charXML, "scale", charPos.scale, 1, 1);
xml.addChild(charXML);
} else {
Logs.trace("Unknown Stage Type : " + Type.getClassName(Type.getClass(button)));
Logs.trace("> Sprite : " + Type.getClassName(Type.getClass(sprite)));
}
}
var charXML:Xml = character.buildXML([
for (button in characterAnimsWindow.buttons.members)
button.anim
]);
// clean
if (charXML.exists("gameOverChar") && character.gameOverCharacter == "bf-dead") charXML.remove("gameOverChar");
if (charXML.exists("camx") && character.cameraOffset.x == 0) charXML.remove("camx");
if (charXML.exists("camy") && character.cameraOffset.y == 0) charXML.remove("camy");
if (charXML.exists("holdTime") && character.holdTime == 4) charXML.remove("holdTime");
if (charXML.exists("flipX") && !character.flipX) charXML.remove("flipX");
if (charXML.exists("scale") && character.scale.x == 1) charXML.remove("scale");
if (charXML.exists("antialiasing") && character.antialiasing) charXML.remove("antialiasing");*/
//if (charXML.exists("gameOverChar") && character.gameOverCharacter == "bf-dead") charXML.remove("gameOverChar");
//if (charXML.exists("camx") && character.cameraOffset.x == 0) charXML.remove("camx");
//if (charXML.exists("camy") && character.cameraOffset.y == 0) charXML.remove("camy");
//if (charXML.exists("holdTime") && character.holdTime == 4) charXML.remove("holdTime");
//if (charXML.exists("flipX") && !character.flipX) charXML.remove("flipX");
//if (charXML.exists("scale") && character.scale.x == 1) charXML.remove("scale");
//if (charXML.exists("antialiasing") && character.antialiasing) charXML.remove("antialiasing");*/
return "<!DOCTYPE codename-engine-stage>\n";// + Printer.print(charXML, true);
Logs.trace(Printer.print(xml, true));
return "<!DOCTYPE codename-engine-stage>\n" + Printer.print(xml, true);
}
/*function _edit_undo(_) {
@@ -562,6 +676,65 @@ class StageEditor extends UIState {
undos.addToUndo(CEditInfo(oldInfo, newInfo));*/
}
public function selectSprite(_sprite:FunkinSprite) {
if(!UIUtil.getKeyState(CONTROL, PRESSED))
_select_deselect(null, false);
if(_sprite is FunkinSprite) {
if(selection.contains(_sprite))
selection.remove(_sprite);
else
selection.push(_sprite);
}
updateSelection();
}
function getSprites() {
return stageSpritesWindow.buttons.members.map((o) -> o.getSprite()).filter((o) -> o != null);
}
function updateSelection() {
var sprites = getSprites();
// Unselect all
for(sprite in sprites) {
if(sprite is FunkinSprite) {
var sprite:FunkinSprite = cast sprite;
sprite.extra.set(exID("selected"), false);
sprite.extra.get(exID("button")).selected = false;
}
}
// Mark selected as selected
for(sprite in selection) {
if(sprite is FunkinSprite) {
var sprite:FunkinSprite = cast sprite;
sprite.extra.set(exID("selected"), true);
sprite.extra.get(exID("button")).selected = true;
Logs.trace("Selected " + sprite.name);
}
}
}
function _select_all(_, checkSelection:Bool = true) {
_select_deselect(null, false);
var sprites = getSprites();
selection = new Selection(sprites);
if(checkSelection) updateSelection();
}
function _select_deselect(_, checkSelection:Bool = true) {
selection = new Selection();
if(checkSelection) updateSelection();
}
function _select_inverse(_, checkSelection:Bool = true) {
var oldSelection = selection;
_select_all(null, false);
for(sprite in oldSelection) {
selection.remove(sprite);
}
if(checkSelection) updateSelection();
}
var zoom(default, set):Float = 0;
var __camZoom(default, set):Float = 1;
function set_zoom(val:Float) {
+15 -8
View File
@@ -1,5 +1,6 @@
package funkin.editors.ui;
import flixel.input.FlxInput.FlxInputState;
import flixel.input.keyboard.FlxKey;
import funkin.editors.ui.UIContextMenu.UIContextMenuOption;
@@ -14,6 +15,19 @@ class UIUtil {
return contextMenu != null && UIState.state.curContextMenu == contextMenu;
}
@:noUsing public static function fixKey(key:FlxKey):FlxKey {
return switch(key) {
#if mac
case CONTROL: WINDOWS; // Remap control to the meta key
#end
default: key;
}
}
public static function getKeyState(key:FlxKey, Status:FlxInputState):Bool {
return FlxG.keys.checkStatus(fixKey(key), Status);
}
/**
* Process all options with shortcuts present in a `Array<UIContextMenuOption>`. Also checks childrens.
* @param topMenuOptions
@@ -41,14 +55,7 @@ class UIUtil {
var shouldPress = Std.int(key) > 0;
if(!shouldPress) key = -key;
var k = switch(key) {
#if mac
case CONTROL:
WINDOWS;
#end
default:
key;
}
var k = fixKey(key);
if (FlxG.keys.checkStatus(k, shouldPress ? JUST_PRESSED : JUST_RELEASED)) {
justPressed = true;
} else if (!FlxG.keys.checkStatus(k, shouldPress ? PRESSED : RELEASED)) {
+54 -29
View File
@@ -184,28 +184,13 @@ class Stage extends FlxBasic implements IBeatReceiver {
}
if (characterPoses["girlfriend"] == null)
addCharPos("girlfriend", null, {
x: 400,
y: 130,
scroll: 0.95,
flip: false
});
addCharPos("girlfriend", null, getDefaultPos("girlfriend"));
if (characterPoses["dad"] == null)
addCharPos("dad", null, {
x: 100,
y: 100,
scroll: 1,
flip: false
});
addCharPos("dad", null, getDefaultPos("dad"));
if (characterPoses["boyfriend"] == null)
addCharPos("boyfriend", null, {
x: 770,
y: 100,
scroll: 1,
flip: true
});
addCharPos("boyfriend", null, getDefaultPos("boyfriend"));
if (PlayState.instance != state) return;
for(k=>e in stageSprites) {
@@ -213,6 +198,35 @@ class Stage extends FlxBasic implements IBeatReceiver {
}
}
public static function getDefaultPos(name:String):StageCharPosInfo {
return switch(name) {
case "boyfriend" | "bf" | "player": {
x: 770,
y: 100,
scroll: 1,
flip: true
};
case "girlfriend" | "gf": {
x: 400,
y: 130,
scroll: 0.95,
flip: false
};
case "dad" | "opponent": {
x: 100,
y: 100,
scroll: 1,
flip: false
};
default: {
x: 0,
y: 0,
scroll: 1,
flip: false
};
}
}
public function addCharPos(name:String, node:Access, ?nonXMLInfo:StageCharPosInfo):StageCharPos {
var charPos = new StageCharPos();
charPos.visible = charPos.active = false;
@@ -227,6 +241,8 @@ class Stage extends FlxBasic implements IBeatReceiver {
if (node != null) {
charPos.x = Std.parseFloat(node.getAtt("x")).getDefault(charPos.x);
charPos.y = Std.parseFloat(node.getAtt("y")).getDefault(charPos.y);
charPos.charSpacingX = Std.parseFloat(node.getAtt("spacingx")).getDefault(charPos.charSpacingX);
charPos.charSpacingY = Std.parseFloat(node.getAtt("spacingy")).getDefault(charPos.charSpacingY);
charPos.camxoffset = Std.parseFloat(node.getAtt("camxoffset")).getDefault(charPos.camxoffset);
charPos.camyoffset = Std.parseFloat(node.getAtt("camyoffset")).getDefault(charPos.camyoffset);
charPos.skewX = Std.parseFloat(node.getAtt("skewx")).getDefault(charPos.skewX);
@@ -234,21 +250,30 @@ class Stage extends FlxBasic implements IBeatReceiver {
charPos.alpha = Std.parseFloat(node.getAtt("alpha")).getDefault(charPos.alpha);
charPos.flipX = (node.has.flip || node.has.flipX) ? (node.getAtt("flip") == "true" || node.getAtt("flipX") == "true") : charPos.flipX;
var scale = Std.parseFloat(node.getAtt("scale")).getDefault(charPos.scale.x);
charPos.scale.set(scale, scale);
if (node.has.scale) {
var scale:Null<Float> = Std.parseFloat(node.att.scale);
if (scale.isNotNull()) charPos.scale.set(scale, scale);
}
if (node.has.scalex) {
var scale:Null<Float> = Std.parseFloat(node.att.scalex);
if (scale.isNotNull()) charPos.scale.x = scale;
}
if (node.has.scaley) {
var scale:Null<Float> = Std.parseFloat(node.att.scaley);
if (scale.isNotNull()) charPos.scale.y = scale;
}
if (node.has.scroll) {
var scroll:Null<Float> = Std.parseFloat(node.att.scroll);
if (scroll != null) charPos.scrollFactor.set(scroll, scroll);
} else {
if (node.has.scrollx) {
var scroll:Null<Float> = Std.parseFloat(node.att.scrollx);
if (scroll != null) charPos.scrollFactor.x = scroll;
}
if (node.has.scrolly) {
var scroll:Null<Float> = Std.parseFloat(node.att.scrolly);
if (scroll != null) charPos.scrollFactor.y = scroll;
}
}
if (node.has.scrollx) {
var scroll:Null<Float> = Std.parseFloat(node.att.scrollx);
if (scroll != null) charPos.scrollFactor.x = scroll;
}
if (node.has.scrolly) {
var scroll:Null<Float> = Std.parseFloat(node.att.scrolly);
if (scroll != null) charPos.scrollFactor.y = scroll;
}
}