Skip to content

Commit

Permalink
the stage editor shit
Browse files Browse the repository at this point in the history
  • Loading branch information
KoloInDaCrib authored Sep 29, 2024
1 parent a27c4ae commit 56cb833
Show file tree
Hide file tree
Showing 24 changed files with 4,025 additions and 3 deletions.
30 changes: 30 additions & 0 deletions source/funkin/data/stage/StageData.hx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class StageData
@:optional
public var cameraZoom:Null<Float>;

@:default("shared")
@:optional
public var directory:Null<String>;

public function new()
{
this.version = StageRegistry.STAGE_DATA_VERSION;
Expand Down Expand Up @@ -182,6 +186,32 @@ typedef StageDataProp =
@:default("sparrow")
@:optional
var animType:String;

/**
* The angle of the prop, as a float.
* @default 1.0
*/
@:optional
@:default(0.0)
var angle:Float;

/**
* The blend mode of the prop, as a string.
* Just like in photoshop.
* @default Nothing.
*/
@:default("")
@:optional
var blend:String;

/**
* The color of the prop overlay, as a hex string.
* White overlays, or the ones with the value #FFFFFF, do not appear.
* @default `#FFFFFF`
*/
@:default("#FFFFFF")
@:optional
var color:String;
};

typedef StageDataCharacter =
Expand Down
4 changes: 4 additions & 0 deletions source/funkin/play/stage/Stage.hx
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
propSprite.scrollFactor.x = dataProp.scroll[0];
propSprite.scrollFactor.y = dataProp.scroll[1];

propSprite.angle = dataProp.angle;
propSprite.color = FlxColor.fromString(dataProp.color);
@:privateAccess if (!isSolidColor) propSprite.blend = BlendMode.fromString(dataProp.blend);

propSprite.zIndex = dataProp.zIndex;

switch (dataProp.animType)
Expand Down
135 changes: 135 additions & 0 deletions source/funkin/save/Save.hx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import funkin.save.migrator.SaveDataMigrator;
import funkin.save.migrator.SaveDataMigrator;
import funkin.ui.debug.charting.ChartEditorState.ChartEditorLiveInputStyle;
import funkin.ui.debug.charting.ChartEditorState.ChartEditorTheme;
import funkin.ui.debug.stageeditor.StageEditorState.StageEditorTheme;
import funkin.util.SerializerUtil;
import thx.semver.Version;
import thx.semver.Version;
Expand Down Expand Up @@ -143,6 +144,14 @@ class Save
hitsoundVolumeOpponent: 1.0,
themeMusic: true
},

optionsStageEditor:
{
previousFiles: [],
moveStep: "1px",
angleStep: 5,
theme: StageEditorTheme.Light
}
};
}

Expand Down Expand Up @@ -425,6 +434,91 @@ class Save
return data.unlocks.oldChar;
}

public var stageEditorPreviousFiles(get, set):Array<String>;

function get_stageEditorPreviousFiles():Array<String>
{
if (data.optionsStageEditor.previousFiles == null) data.optionsStageEditor.previousFiles = [];

return data.optionsStageEditor.previousFiles;
}

function set_stageEditorPreviousFiles(value:Array<String>):Array<String>
{
// Set and apply.
data.optionsStageEditor.previousFiles = value;
flush();
return data.optionsStageEditor.previousFiles;
}

public var stageEditorHasBackup(get, set):Bool;

function get_stageEditorHasBackup():Bool
{
if (data.optionsStageEditor.hasBackup == null) data.optionsStageEditor.hasBackup = false;

return data.optionsStageEditor.hasBackup;
}

function set_stageEditorHasBackup(value:Bool):Bool
{
// Set and apply.
data.optionsStageEditor.hasBackup = value;
flush();
return data.optionsStageEditor.hasBackup;
}

public var stageEditorMoveStep(get, set):String;

function get_stageEditorMoveStep():String
{
if (data.optionsStageEditor.moveStep == null) data.optionsStageEditor.moveStep = "1px";

return data.optionsStageEditor.moveStep;
}

function set_stageEditorMoveStep(value:String):String
{
// Set and apply.
data.optionsStageEditor.moveStep = value;
flush();
return data.optionsStageEditor.moveStep;
}

public var stageEditorAngleStep(get, set):Float;

function get_stageEditorAngleStep():Float
{
if (data.optionsStageEditor.angleStep == null) data.optionsStageEditor.angleStep = 5;

return data.optionsStageEditor.angleStep;
}

function set_stageEditorAngleStep(value:Float):Float
{
// Set and apply.
data.optionsStageEditor.angleStep = value;
flush();
return data.optionsStageEditor.angleStep;
}

public var stageEditorTheme(get, set):StageEditorTheme;

function get_stageEditorTheme():StageEditorTheme
{
if (data.optionsStageEditor.theme == null) data.optionsStageEditor.theme = StageEditorTheme.Light;

return data.optionsStageEditor.theme;
}

function set_stageEditorTheme(value:StageEditorTheme):StageEditorTheme
{
// Set and apply.
data.optionsStageEditor.theme = value;
flush();
return data.optionsStageEditor.theme;
}

/**
* When we've seen a character unlock, add it to the list of characters seen.
* @param character
Expand Down Expand Up @@ -1031,6 +1125,11 @@ typedef RawSaveData =
* The user's preferences specific to the Chart Editor.
*/
var optionsChartEditor:SaveDataChartEditorOptions;

/**
* The user's preferences specific to the Stage Editor.
*/
var optionsStageEditor:SaveDataStageEditorOptions;
};

typedef SaveApiData =
Expand Down Expand Up @@ -1398,3 +1497,39 @@ typedef SaveDataChartEditorOptions =
*/
var ?playbackSpeed:Float;
};

typedef SaveDataStageEditorOptions =
{
// a lot of these things were copied from savedatacharteditoroptions

/**
* Whether the Stage Editor created a backup the last time it closed.
* Prompt the user to load it, then set this back to `false`.
* @default `false`
*/
var ?hasBackup:Bool;

/**
* Previous files opened in the Stage Editor.
* @default `[]`
*/
var ?previousFiles:Array<String>;

/**
* The Step at which an Object or Character is moved.
* @default `1px`
*/
var ?moveStep:String;

/**
* The Step at which an Object is rotated.
* @default `5`
*/
var ?angleStep:Float;

/**
* Theme in the Stage Editor.
* @default `StageEditorTheme.Light`
*/
var ?theme:StageEditorTheme;
};
3 changes: 2 additions & 1 deletion source/funkin/ui/debug/DebugMenuSubState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class DebugMenuSubState extends MusicBeatSubState
// createItem("Input Offset Testing", openInputOffsetTesting);
createItem("CHARACTER SELECT", openCharSelect, true);
createItem("ANIMATION EDITOR", openAnimationEditor);
// createItem("STAGE EDITOR", openStageEditor);
createItem("STAGE EDITOR", openStageEditor);
// createItem("TEST STICKERS", testStickers);
#if sys
createItem("OPEN CRASH LOG FOLDER", openLogFolder);
Expand Down Expand Up @@ -125,6 +125,7 @@ class DebugMenuSubState extends MusicBeatSubState
function openStageEditor()
{
trace('Stage Editor');
FlxG.switchState(() -> new funkin.ui.debug.stageeditor.StageEditorState());
}

#if sys
Expand Down
119 changes: 119 additions & 0 deletions source/funkin/ui/debug/stageeditor/StageEditorObject.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package funkin.ui.debug.stageeditor;

import funkin.data.animation.AnimationData;
import funkin.graphics.FunkinSprite;
import funkin.modding.events.ScriptEvent;

/**
* Contains all the Logic needed for Stage Editor. Only for Stage Editor, as in the gameplay StageProps and Boppers will be used.
*/
class StageEditorObject extends FunkinSprite
{
/**
* The internal Name of the Object.
*/
public var name:String = "Unnamed";

/**
* What animation to play upon starting.
*/
public var startingAnimation:String = "";

public var animDatas:Map<String, AnimationData> = [];

override public function new()
{
super();
}

/**
* Whether the Object is currently being modified in the Stage Editor.
*/
public var isDebugged(default, set):Bool = true;

function set_isDebugged(value:Bool)
{
this.isDebugged = value;

if (value == false) // plays upon starting yippee!!!
playAnim(startingAnimation, true);
else
{
if (animation.curAnim != null)
{
animation.stop();
offset.set();
updateHitbox();
}
}

return value;
}

public function playAnim(name:String, restart:Bool = false, reversed:Bool = false)
{
if (!animation.getNameList().contains(name)) return;

animation.play(name, restart, reversed, 0);

if (animDatas.exists(name)) offset.set(animDatas[name].offsets[0], animDatas[name].offsets[1]);
else
offset.set();
}

/**
* On which beat should it dance?
*/
public var danceEvery:Float = 0;

/**
* Internal, handles danceLeft and danceRight.
*/
var _danced:Bool = true;

public function dance(restart:Bool = false)
{
if (isDebugged) return;

var idle = animation.getNameList().contains("idle");
var dancing = animation.getNameList().contains("danceLeft") && animation.getNameList().contains("danceRight");

if (!idle && !dancing) return;

if (dancing)
{
if (_danced) playAnim("danceRight", restart);
else
playAnim("danceLeft", restart);

_danced = !_danced;
}
else if (idle)
{
playAnim("idle", restart);
}
}

public function addAnim(name:String, prefix:String, offsets:Array<Float>, indices:Array<Int>, frameRate:Int = 24, looped:Bool = true, flipX:Bool = false,
flipY:Bool = false)
{
if (indices.length > 0) animation.addByIndices(name, prefix, indices, "", frameRate, looped, flipX, flipY);
else
animation.addByPrefix(name, prefix, frameRate, looped, flipX, flipY);

if (animation.getNameList().contains(name)) // sometimes the animation doesnt add
{
animDatas.set(name,
{
name: name,
prefix: prefix,
offsets: offsets,
looped: looped,
frameRate: frameRate,
flipX: flipX,
flipY: flipY,
frameIndices: indices
});
}
}
}
Loading

0 comments on commit 56cb833

Please sign in to comment.