FUCK SPACES!!!! TABS RULES!!! 💪💪💪💪

This commit is contained in:
Yoshman29
2023-03-25 22:53:47 +01:00
parent c259385f2a
commit a63e5f5958
135 changed files with 6799 additions and 6799 deletions
+96 -96
View File
@@ -17,134 +17,134 @@ using StringTools;
class AtlasFrameMaker extends FlxFramesCollection{
//public static var widthoffset:Int = 0;
//public static var heightoffset:Int = 0;
//public static var excludeArray:Array<String>;
/**
//public static var widthoffset:Int = 0;
//public static var heightoffset:Int = 0;
//public static var excludeArray:Array<String>;
/**
* Creates Frames from TextureAtlas(very early and broken ok) Originally made for FNF HD by Smokey and Rozebud
*
* @param key The file path.
* @param _excludeArray Use this to only create selected animations. Keep null to create all of them.
* @param key The file path.
* @param _excludeArray Use this to only create selected animations. Keep null to create all of them.
*
*/
public static function construct(key:String,?_excludeArray:Array<String> = null):FlxFramesCollection{
public static function construct(key:String,?_excludeArray:Array<String> = null):FlxFramesCollection{
// widthoffset = _widthoffset;
// heightoffset = _heightoffset;
// widthoffset = _widthoffset;
// heightoffset = _heightoffset;
var frameCollection:FlxFramesCollection;
var frameArray:Array<Array<FlxFrame>> = [];
var animationData:AnimationData = Json.parse(Assets.getText(key + "/Animation.json"));
var atlasData:AtlasData = Json.parse(Assets.getText(key + "/spritemap.json").replace("\uFEFF", ""));//FIXED UTF8 w/ BOM error
var bitmapData:BitmapData = Assets.getBitmapData(key + "/spritemap.png");
var ss = new SpriteAnimationLibrary(animationData, atlasData, bitmapData);
var t = ss.createAnimation();
if(_excludeArray == null){
_excludeArray = t.getFrameLabels();
}
frameCollection = new FlxFramesCollection(FlxGraphic.fromBitmapData(bitmapData),FlxFrameCollectionType.IMAGE);
var frameCollection:FlxFramesCollection;
var frameArray:Array<Array<FlxFrame>> = [];
var animationData:AnimationData = Json.parse(Assets.getText(key + "/Animation.json"));
var atlasData:AtlasData = Json.parse(Assets.getText(key + "/spritemap.json").replace("\uFEFF", ""));//FIXED UTF8 w/ BOM error
var bitmapData:BitmapData = Assets.getBitmapData(key + "/spritemap.png");
var ss = new SpriteAnimationLibrary(animationData, atlasData, bitmapData);
var t = ss.createAnimation();
if(_excludeArray == null){
_excludeArray = t.getFrameLabels();
}
frameCollection = new FlxFramesCollection(FlxGraphic.fromBitmapData(bitmapData),FlxFrameCollectionType.IMAGE);
for(x in t.getFrameLabels()){
for(x in t.getFrameLabels()){
frameArray.push(getFramesArray(t, x,_excludeArray));
frameArray.push(getFramesArray(t, x,_excludeArray));
}
}
for(x in frameArray){
for(y in x){
frameCollection.pushFrame(y);
}
}
for(x in frameArray){
for(y in x){
frameCollection.pushFrame(y);
}
}
return frameCollection;
return frameCollection;
}
}
@:noCompletion static function getFramesArray(t:SpriteMovieClip,animation:String,_excludeArray:Array<String>):Array<FlxFrame>
{
var sizeInfo:Rectangle = new Rectangle(0,0);
t.currentLabel = animation;
var bitMapArray:Array<BitmapData> = [];
var daFramez:Array<FlxFrame> = [];
var firstPass = true;
var frameSize:FlxPoint = new FlxPoint(0,0);
@:noCompletion static function getFramesArray(t:SpriteMovieClip,animation:String,_excludeArray:Array<String>):Array<FlxFrame>
{
var sizeInfo:Rectangle = new Rectangle(0,0);
t.currentLabel = animation;
var bitMapArray:Array<BitmapData> = [];
var daFramez:Array<FlxFrame> = [];
var firstPass = true;
var frameSize:FlxPoint = new FlxPoint(0,0);
for (i in t.getFrame(animation)...t.numFrames){
t.currentFrame = i;
if (t.currentLabel == animation){
if (_excludeArray.contains(animation)){
sizeInfo = t.getBounds(t);
for (i in t.getFrame(animation)...t.numFrames){
t.currentFrame = i;
if (t.currentLabel == animation){
if (_excludeArray.contains(animation)){
sizeInfo = t.getBounds(t);
var bitmapShit:BitmapData = new BitmapData(
Std.int(sizeInfo.width + Math.abs(sizeInfo.x)),Std.int(sizeInfo.height +Math.abs(sizeInfo.y)),true,0);
var bitmapShit:BitmapData = new BitmapData(
Std.int(sizeInfo.width + Math.abs(sizeInfo.x)),Std.int(sizeInfo.height +Math.abs(sizeInfo.y)),true,0);
bitmapShit.draw(t,null,null,null,null,true);
bitMapArray.push(bitmapShit);
bitmapShit.draw(t,null,null,null,null,true);
bitMapArray.push(bitmapShit);
if (firstPass){
frameSize.set(bitmapShit.width,bitmapShit.height);
firstPass = false;
}
}
}
else break;
}
if (firstPass){
frameSize.set(bitmapShit.width,bitmapShit.height);
firstPass = false;
}
}
}
else break;
}
for (i in 0...bitMapArray.length){
var b = FlxGraphic.fromBitmapData(bitMapArray[i]);
var theFrame = new FlxFrame(b);
theFrame.parent = b;
theFrame.name = animation + i;
theFrame.sourceSize.set(frameSize.x,frameSize.y);
theFrame.frame = new FlxRect(0, 0, bitMapArray[i].width, bitMapArray[i].height);
daFramez.push(theFrame);
for (i in 0...bitMapArray.length){
var b = FlxGraphic.fromBitmapData(bitMapArray[i]);
var theFrame = new FlxFrame(b);
theFrame.parent = b;
theFrame.name = animation + i;
theFrame.sourceSize.set(frameSize.x,frameSize.y);
theFrame.frame = new FlxRect(0, 0, bitMapArray[i].width, bitMapArray[i].height);
daFramez.push(theFrame);
//trace(daFramez);
}
//trace(daFramez);
}
if (frameSize != null)
frameSize.put();
if (frameSize != null)
frameSize.put();
return daFramez;
}
return daFramez;
}
/*public static function renderTest(key:String, animation:String, ?frame:Int = 0):Void
{
var animationData:AnimationData = Json.parse(Assets.getText(key + "/Animation.json"));
var atlasData:AtlasData = Json.parse(Assets.getText(key + "/spritemap.json"));
var bitmapData:BitmapData = Assets.getBitmapData(key + "/spritemap.png");
var ss = new SpriteAnimationLibrary(animationData, atlasData, bitmapData);
var t = ss.createAnimation();
var bitMapArray:Array<BitmapData> = [];
/*public static function renderTest(key:String, animation:String, ?frame:Int = 0):Void
{
var animationData:AnimationData = Json.parse(Assets.getText(key + "/Animation.json"));
var atlasData:AtlasData = Json.parse(Assets.getText(key + "/spritemap.json"));
var bitmapData:BitmapData = Assets.getBitmapData(key + "/spritemap.png");
var ss = new SpriteAnimationLibrary(animationData, atlasData, bitmapData);
var t = ss.createAnimation();
var bitMapArray:Array<BitmapData> = [];
for (i in 0...t.numFrames){
t.currentFrame = i;
if (t.currentLabel == animation){
//trace(t.currentFrame);
var bitmapShit:BitmapData = new BitmapData(Std.int(t.width),Std.int(t.height),true,0);
//bitmapShit.drawWithQuality(t,null,null,null,null,true);
bitmapShit.draw(t, new Matrix(1, 0, 0, 1, t.width/2, t.height/2), null, null, null, false);
bitMapArray.push(bitmapShit);
}
}
for (i in 0...t.numFrames){
t.currentFrame = i;
if (t.currentLabel == animation){
//trace(t.currentFrame);
var bitmapShit:BitmapData = new BitmapData(Std.int(t.width),Std.int(t.height),true,0);
//bitmapShit.drawWithQuality(t,null,null,null,null,true);
bitmapShit.draw(t, new Matrix(1, 0, 0, 1, t.width/2, t.height/2), null, null, null, false);
bitMapArray.push(bitmapShit);
}
}
saveImage(bitMapArray[frame]);
saveImage(bitMapArray[frame]);
}
}
public static function saveImage(bitmapData:BitmapData)
{
var b:ByteArray = new ByteArray();
b = bitmapData.encode(bitmapData.rect, new PNGEncoderOptions(true), b);
new FileDialog().save(b, "png", null, "file");
}
*/
public static function saveImage(bitmapData:BitmapData)
{
var b:ByteArray = new ByteArray();
b = bitmapData.encode(bitmapData.rect, new PNGEncoderOptions(true), b);
new FileDialog().save(b, "png", null, "file");
}
*/
+112 -112
View File
@@ -29,146 +29,146 @@ import flixel.FlxCamera;
import away3d.containers.View3D;
class Flx3DCamera extends FlxCamera {
private static var __3DIDS:Int = 0;
private static var __3DIDS:Int = 0;
public var view:View3D;
public var view:View3D;
var meshes:Array<Mesh> = [];
public function new(X:Int = 0, Y:Int = 0, Width:Int = 0, Height:Int = 0, DefaultZoom:Float = 1) {
if (!Flx3DUtil.is3DAvailable())
throw "[Flx3DCamera] 3D is not available on this platform. Stages in use: " + Flx3DUtil.getTotal3D() + ", Max stages allowed: " + FlxG.stage.stage3Ds.length + ".";
super(X, Y, Width, Height, DefaultZoom);
__cur3DStageID = __3DIDS++;
var meshes:Array<Mesh> = [];
public function new(X:Int = 0, Y:Int = 0, Width:Int = 0, Height:Int = 0, DefaultZoom:Float = 1) {
if (!Flx3DUtil.is3DAvailable())
throw "[Flx3DCamera] 3D is not available on this platform. Stages in use: " + Flx3DUtil.getTotal3D() + ", Max stages allowed: " + FlxG.stage.stage3Ds.length + ".";
super(X, Y, Width, Height, DefaultZoom);
__cur3DStageID = __3DIDS++;
view = new View3D();
view.width = this.width;
view.height = this.height;
view.visible = true;
view.width = this.width;
view.height = this.height;
view.visible = true;
FlxG.stage.addChild(view);
}
FlxG.stage.addChild(view);
}
public override function render() {
super.render();
public override function render() {
super.render();
view.x = FlxG.game.x + FlxG.game.scaleX * (flashSprite.x + flashSprite.scaleX * (_scrollRect.x + _scrollRect.scaleX * (_scrollRect.scrollRect.x)));
view.x -= _scrollRect.scrollRect.width * ((zoom / initialZoom) - 1) / 2;
view.y = FlxG.game.y + FlxG.game.scaleY * (flashSprite.y + flashSprite.scaleY * (_scrollRect.y + _scrollRect.scaleY * (_scrollRect.scrollRect.y)));
view.y -= _scrollRect.scrollRect.height * ((zoom / initialZoom) - 1) / 2;
view.x = FlxG.game.x + FlxG.game.scaleX * (flashSprite.x + flashSprite.scaleX * (_scrollRect.x + _scrollRect.scaleX * (_scrollRect.scrollRect.x)));
view.x -= _scrollRect.scrollRect.width * ((zoom / initialZoom) - 1) / 2;
view.y = FlxG.game.y + FlxG.game.scaleY * (flashSprite.y + flashSprite.scaleY * (_scrollRect.y + _scrollRect.scaleY * (_scrollRect.scrollRect.y)));
view.y -= _scrollRect.scrollRect.height * ((zoom / initialZoom) - 1) / 2;
view.width = _scrollRect.scrollRect.width / initialZoom;
view.width += _scrollRect.scrollRect.width / initialZoom * ((zoom / initialZoom) - 1);
view.height = _scrollRect.scrollRect.height / initialZoom;
view.height += _scrollRect.scrollRect.height / initialZoom * ((zoom / initialZoom) - 1);
view.width = _scrollRect.scrollRect.width / initialZoom;
view.width += _scrollRect.scrollRect.width / initialZoom * ((zoom / initialZoom) - 1);
view.height = _scrollRect.scrollRect.height / initialZoom;
view.height += _scrollRect.scrollRect.height / initialZoom * ((zoom / initialZoom) - 1);
view.render();
}
view.render();
}
public function addModel(assetPath:String, callback:Asset3DEvent->Void, ?texturePath:String, smoothTexture:Bool = true) {
var model = Assets.getBytes(assetPath);
if (model == null)
throw 'Model at ${assetPath} was not found.';
var model = Assets.getBytes(assetPath);
if (model == null)
throw 'Model at ${assetPath} was not found.';
var context = new AssetLoaderContext();
var noExt = Path.withoutExtension(assetPath);
trace(noExt);
context.mapUrlToData('${Path.withoutDirectory(noExt)}.mtl', '$noExt.mtl');
var context = new AssetLoaderContext();
var noExt = Path.withoutExtension(assetPath);
trace(noExt);
context.mapUrlToData('${Path.withoutDirectory(noExt)}.mtl', '$noExt.mtl');
var material:TextureMaterial = null;
if (texturePath != null)
material = new TextureMaterial(Cast.bitmapTexture(texturePath), smoothTexture);
var material:TextureMaterial = null;
if (texturePath != null)
material = new TextureMaterial(Cast.bitmapTexture(texturePath), smoothTexture);
return loadData(model, context, switch(Path.extension(assetPath).toLowerCase()) {
case "dae": new DAEParser();
case "md2": new MD2Parser();
case "md5": new MD5MeshParser();
case "awd": new AWDParser();
default: new OBJParser();
}, (event:Asset3DEvent) -> {
if (event.asset != null && event.asset.assetType == Asset3DType.MESH) {
var mesh:Mesh = cast(event.asset, Mesh);
if (material != null)
mesh.material = material;
meshes.push(mesh);
}
callback(event);
});
return loadData(model, context, switch(Path.extension(assetPath).toLowerCase()) {
case "dae": new DAEParser();
case "md2": new MD2Parser();
case "md5": new MD5MeshParser();
case "awd": new AWDParser();
default: new OBJParser();
}, (event:Asset3DEvent) -> {
if (event.asset != null && event.asset.assetType == Asset3DType.MESH) {
var mesh:Mesh = cast(event.asset, Mesh);
if (material != null)
mesh.material = material;
meshes.push(mesh);
}
callback(event);
});
}
private var __cur3DStageID:Int;
private var _loaders:Map<Asset3DLibraryBundle, AssetLoaderToken> = [];
private var __cur3DStageID:Int;
private var _loaders:Map<Asset3DLibraryBundle, AssetLoaderToken> = [];
private function loadData(data:Dynamic, context:AssetLoaderContext, parser:ParserBase, onAssetCallback:Asset3DEvent->Void):AssetLoaderToken {
var token:AssetLoaderToken;
private function loadData(data:Dynamic, context:AssetLoaderContext, parser:ParserBase, onAssetCallback:Asset3DEvent->Void):AssetLoaderToken {
var token:AssetLoaderToken;
var lib:Asset3DLibraryBundle;
lib = Asset3DLibraryBundle.getInstance('Flx3DView-${__cur3DStageID}');
token = lib.loadData(data, context, null, parser);
var lib:Asset3DLibraryBundle;
lib = Asset3DLibraryBundle.getInstance('Flx3DView-${__cur3DStageID}');
token = lib.loadData(data, context, null, parser);
token.addEventListener(Asset3DEvent.ASSET_COMPLETE, (event:Asset3DEvent) -> {
// ! Taken from Loader3D https://github.com/openfl/away3d/blob/master/away3d/loaders/Loader3D.hx#L207-L232
if (event.type == Asset3DEvent.ASSET_COMPLETE) {
var obj:ObjectContainer3D = null;
switch (event.asset.assetType) {
case Asset3DType.LIGHT:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, LightBase) ? cast event.asset : null;
case Asset3DType.CONTAINER:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, ObjectContainer3D) ? cast event.asset : null;
case Asset3DType.MESH:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, Mesh) ? cast event.asset : null;
case Asset3DType.SKYBOX:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, SkyBox) ? cast event.asset : null;
case Asset3DType.TEXTURE_PROJECTOR:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, TextureProjector) ? cast event.asset : null;
case Asset3DType.CAMERA:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, Camera3D) ? cast event.asset : null;
case Asset3DType.SEGMENT_SET:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, SegmentSet) ? cast event.asset : null;
}
if (obj != null && obj.parent == null)
view.scene.addChild(obj);
}
token.addEventListener(Asset3DEvent.ASSET_COMPLETE, (event:Asset3DEvent) -> {
// ! Taken from Loader3D https://github.com/openfl/away3d/blob/master/away3d/loaders/Loader3D.hx#L207-L232
if (event.type == Asset3DEvent.ASSET_COMPLETE) {
var obj:ObjectContainer3D = null;
switch (event.asset.assetType) {
case Asset3DType.LIGHT:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, LightBase) ? cast event.asset : null;
case Asset3DType.CONTAINER:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, ObjectContainer3D) ? cast event.asset : null;
case Asset3DType.MESH:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, Mesh) ? cast event.asset : null;
case Asset3DType.SKYBOX:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, SkyBox) ? cast event.asset : null;
case Asset3DType.TEXTURE_PROJECTOR:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, TextureProjector) ? cast event.asset : null;
case Asset3DType.CAMERA:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, Camera3D) ? cast event.asset : null;
case Asset3DType.SEGMENT_SET:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, SegmentSet) ? cast event.asset : null;
}
if (obj != null && obj.parent == null)
view.scene.addChild(obj);
}
if (onAssetCallback != null)
onAssetCallback(event);
});
if (onAssetCallback != null)
onAssetCallback(event);
});
token.addEventListener(LoaderEvent.RESOURCE_COMPLETE, (_) -> {
trace("Loader Finished...");
});
token.addEventListener(LoaderEvent.RESOURCE_COMPLETE, (_) -> {
trace("Loader Finished...");
});
_loaders.set(lib,token);
_loaders.set(lib,token);
return token;
}
return token;
}
override function destroy() {
if (meshes != null)
for(mesh in meshes)
mesh.dispose();
override function destroy() {
if (meshes != null)
for(mesh in meshes)
mesh.dispose();
var bundle = Asset3DLibraryBundle.getInstance('Flx3DView-${__cur3DStageID}');
bundle.stopAllLoadingSessions();
@:privateAccess {
if (bundle._loadingSessions != null) {
for(load in bundle._loadingSessions) {
load.dispose();
}
}
Asset3DLibrary._instances.remove('Flx3DView-${__cur3DStageID}');
}
var bundle = Asset3DLibraryBundle.getInstance('Flx3DView-${__cur3DStageID}');
bundle.stopAllLoadingSessions();
@:privateAccess {
if (bundle._loadingSessions != null) {
for(load in bundle._loadingSessions) {
load.dispose();
}
}
Asset3DLibrary._instances.remove('Flx3DView-${__cur3DStageID}');
}
FlxG.stage.removeChild(view);
try {
view.dispose();
} catch(e) {
FlxG.stage.removeChild(view);
try {
view.dispose();
} catch(e) {
}
}
super.destroy();
}
super.destroy();
}
public inline function addChild(c)
view.scene.addChild(c);
public inline function addChild(c)
view.scene.addChild(c);
}
+93 -93
View File
@@ -29,120 +29,120 @@ import funkin.windows.WindowsAPI.ConsoleColor;
// FlxView3D with helpers for easier updating
class Flx3DView extends FlxView3D {
private static var __3DIDS:Int = 0;
private static var __3DIDS:Int = 0;
var meshes:Array<Mesh> = [];
public function new(x:Float = 0, y:Float = 0, width:Int = -1, height:Int = -1) {
if (!Flx3DUtil.is3DAvailable())
throw "[Flx3DView] 3D is not available on this platform. Stages in use: " + Flx3DUtil.getTotal3D() + ", Max stages allowed: " + FlxG.stage.stage3Ds.length + ".";
super(x, y, width, height);
__cur3DStageID = __3DIDS++;
}
var meshes:Array<Mesh> = [];
public function new(x:Float = 0, y:Float = 0, width:Int = -1, height:Int = -1) {
if (!Flx3DUtil.is3DAvailable())
throw "[Flx3DView] 3D is not available on this platform. Stages in use: " + Flx3DUtil.getTotal3D() + ", Max stages allowed: " + FlxG.stage.stage3Ds.length + ".";
super(x, y, width, height);
__cur3DStageID = __3DIDS++;
}
public function addModel(assetPath:String, callback:Asset3DEvent->Void, ?texturePath:String, smoothTexture:Bool = true) {
var model = Assets.getBytes(assetPath);
if (model == null)
throw 'Model at ${assetPath} was not found.';
var model = Assets.getBytes(assetPath);
if (model == null)
throw 'Model at ${assetPath} was not found.';
var context = new AssetLoaderContext();
var noExt = Path.withoutExtension(assetPath);
trace(noExt);
context.mapUrlToData('${Path.withoutDirectory(noExt)}.mtl', '$noExt.mtl');
var context = new AssetLoaderContext();
var noExt = Path.withoutExtension(assetPath);
trace(noExt);
context.mapUrlToData('${Path.withoutDirectory(noExt)}.mtl', '$noExt.mtl');
var material:TextureMaterial = null;
if (texturePath != null)
material = new TextureMaterial(Cast.bitmapTexture(texturePath), smoothTexture);
var material:TextureMaterial = null;
if (texturePath != null)
material = new TextureMaterial(Cast.bitmapTexture(texturePath), smoothTexture);
return loadData(model, context, switch(Path.extension(assetPath).toLowerCase()) {
case "dae": new DAEParser();
case "md2": new MD2Parser();
case "md5": new MD5MeshParser();
case "awd": new AWDParser();
default: new OBJParser();
}, (event:Asset3DEvent) -> {
if (event.asset != null && event.asset.assetType == Asset3DType.MESH) {
var mesh:Mesh = cast(event.asset, Mesh);
if (material != null)
mesh.material = material;
meshes.push(mesh);
}
callback(event);
});
return loadData(model, context, switch(Path.extension(assetPath).toLowerCase()) {
case "dae": new DAEParser();
case "md2": new MD2Parser();
case "md5": new MD5MeshParser();
case "awd": new AWDParser();
default: new OBJParser();
}, (event:Asset3DEvent) -> {
if (event.asset != null && event.asset.assetType == Asset3DType.MESH) {
var mesh:Mesh = cast(event.asset, Mesh);
if (material != null)
mesh.material = material;
meshes.push(mesh);
}
callback(event);
});
}
@:deprecated public function addMesh(assetPath:String, callback:Mesh->Void, ?texturePath:String, smoothTexture:Bool = true) {
Logs.trace('The addMesh() function is deprecated, use addModel instead!', ERROR, RED);
}
@:deprecated public function addMesh(assetPath:String, callback:Mesh->Void, ?texturePath:String, smoothTexture:Bool = true) {
Logs.trace('The addMesh() function is deprecated, use addModel instead!', ERROR, RED);
}
private var __cur3DStageID:Int;
private var _loaders:Map<Asset3DLibraryBundle, AssetLoaderToken> = [];
private var __cur3DStageID:Int;
private var _loaders:Map<Asset3DLibraryBundle, AssetLoaderToken> = [];
private function loadData(data:Dynamic, context:AssetLoaderContext, parser:ParserBase, onAssetCallback:Asset3DEvent->Void):AssetLoaderToken {
var token:AssetLoaderToken;
private function loadData(data:Dynamic, context:AssetLoaderContext, parser:ParserBase, onAssetCallback:Asset3DEvent->Void):AssetLoaderToken {
var token:AssetLoaderToken;
var lib:Asset3DLibraryBundle;
lib = Asset3DLibraryBundle.getInstance('Flx3DView-${__cur3DStageID}');
token = lib.loadData(data, context, null, parser);
var lib:Asset3DLibraryBundle;
lib = Asset3DLibraryBundle.getInstance('Flx3DView-${__cur3DStageID}');
token = lib.loadData(data, context, null, parser);
token.addEventListener(Asset3DEvent.ASSET_COMPLETE, (event:Asset3DEvent) -> {
// ! Taken from Loader3D https://github.com/openfl/away3d/blob/master/away3d/loaders/Loader3D.hx#L207-L232
if (event.type == Asset3DEvent.ASSET_COMPLETE) {
var obj:ObjectContainer3D = null;
switch (event.asset.assetType) {
case Asset3DType.LIGHT:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, LightBase) ? cast event.asset : null;
case Asset3DType.CONTAINER:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, ObjectContainer3D) ? cast event.asset : null;
case Asset3DType.MESH:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, Mesh) ? cast event.asset : null;
case Asset3DType.SKYBOX:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, SkyBox) ? cast event.asset : null;
case Asset3DType.TEXTURE_PROJECTOR:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, TextureProjector) ? cast event.asset : null;
case Asset3DType.CAMERA:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, Camera3D) ? cast event.asset : null;
case Asset3DType.SEGMENT_SET:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, SegmentSet) ? cast event.asset : null;
}
if (obj != null && obj.parent == null)
view.scene.addChild(obj);
}
token.addEventListener(Asset3DEvent.ASSET_COMPLETE, (event:Asset3DEvent) -> {
// ! Taken from Loader3D https://github.com/openfl/away3d/blob/master/away3d/loaders/Loader3D.hx#L207-L232
if (event.type == Asset3DEvent.ASSET_COMPLETE) {
var obj:ObjectContainer3D = null;
switch (event.asset.assetType) {
case Asset3DType.LIGHT:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, LightBase) ? cast event.asset : null;
case Asset3DType.CONTAINER:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, ObjectContainer3D) ? cast event.asset : null;
case Asset3DType.MESH:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, Mesh) ? cast event.asset : null;
case Asset3DType.SKYBOX:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, SkyBox) ? cast event.asset : null;
case Asset3DType.TEXTURE_PROJECTOR:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, TextureProjector) ? cast event.asset : null;
case Asset3DType.CAMERA:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, Camera3D) ? cast event.asset : null;
case Asset3DType.SEGMENT_SET:
obj = #if (haxe_ver >= 4.2) Std.isOfType #else Std.is #end(event.asset, SegmentSet) ? cast event.asset : null;
}
if (obj != null && obj.parent == null)
view.scene.addChild(obj);
}
if (onAssetCallback != null)
onAssetCallback(event);
});
if (onAssetCallback != null)
onAssetCallback(event);
});
token.addEventListener(LoaderEvent.RESOURCE_COMPLETE, (_) -> {
trace("Loader Finished...");
token.addEventListener(LoaderEvent.RESOURCE_COMPLETE, (_) -> {
trace("Loader Finished...");
});
});
_loaders.set(lib,token);
_loaders.set(lib,token);
return token;
}
return token;
}
override function destroy() {
if (meshes != null)
for(mesh in meshes)
mesh.dispose();
override function destroy() {
if (meshes != null)
for(mesh in meshes)
mesh.dispose();
var bundle = Asset3DLibraryBundle.getInstance('Flx3DView-${__cur3DStageID}');
bundle.stopAllLoadingSessions();
@:privateAccess {
if (bundle._loadingSessions != null) {
for(load in bundle._loadingSessions) {
load.dispose();
}
}
Asset3DLibrary._instances.remove('Flx3DView-${__cur3DStageID}');
}
var bundle = Asset3DLibraryBundle.getInstance('Flx3DView-${__cur3DStageID}');
bundle.stopAllLoadingSessions();
@:privateAccess {
if (bundle._loadingSessions != null) {
for(load in bundle._loadingSessions) {
load.dispose();
}
}
Asset3DLibrary._instances.remove('Flx3DView-${__cur3DStageID}');
}
super.destroy();
}
super.destroy();
}
public inline function addChild(c)
view.scene.addChild(c);
public inline function addChild(c)
view.scene.addChild(c);
}
+82 -82
View File
@@ -1,102 +1,102 @@
package funkin.chart;
class BaseGameParser {
public static function parse(data:Dynamic, result:ChartData) {
// base fnf chart parsing
var data:SwagSong = data;
if (Reflect.hasField(data, "song")) {
var field:Dynamic = Reflect.field(data, "song");
if (!(field is String))
data = field;
}
public static function parse(data:Dynamic, result:ChartData) {
// base fnf chart parsing
var data:SwagSong = data;
if (Reflect.hasField(data, "song")) {
var field:Dynamic = Reflect.field(data, "song");
if (!(field is String))
data = field;
}
result.scrollSpeed = data.speed;
result.stage = data.stage;
result.scrollSpeed = data.speed;
result.stage = data.stage;
result.strumLines.push({
characters: [data.player2],
type: 0,
position: data.player2.startsWith("gf") ? "girlfriend" : "dad",
notes: []
});
result.strumLines.push({
characters: [data.player1],
type: 1,
position: "boyfriend",
notes: []
});
if (data.gf != "none") {
result.strumLines.push({
characters: [data.gf != null ? data.gf : "gf"],
type: 2,
position: "girlfriend",
notes: [],
visible: false,
strumLinePos: 0.5
});
}
result.strumLines.push({
characters: [data.player2],
type: 0,
position: data.player2.startsWith("gf") ? "girlfriend" : "dad",
notes: []
});
result.strumLines.push({
characters: [data.player1],
type: 1,
position: "boyfriend",
notes: []
});
if (data.gf != "none") {
result.strumLines.push({
characters: [data.gf != null ? data.gf : "gf"],
type: 2,
position: "girlfriend",
notes: [],
visible: false,
strumLinePos: 0.5
});
}
result.meta.bpm = data.bpm;
result.meta.bpm = data.bpm;
var camFocusedBF:Bool = false;
var beatsPerMesure:Float = data.beatsPerMesure.getDefault(4);
var curBPM:Float = data.bpm;
var curTime:Float = 0;
var curCrochet:Float = ((60 / curBPM) * 1000);
var camFocusedBF:Bool = false;
var beatsPerMesure:Float = data.beatsPerMesure.getDefault(4);
var curBPM:Float = data.bpm;
var curTime:Float = 0;
var curCrochet:Float = ((60 / curBPM) * 1000);
if (data.notes != null) for(section in data.notes) {
if (section == null) {
curTime += curCrochet * beatsPerMesure;
continue; // Yoshi Engine charts crash fix
}
if (data.notes != null) for(section in data.notes) {
if (section == null) {
curTime += curCrochet * beatsPerMesure;
continue; // Yoshi Engine charts crash fix
}
if (camFocusedBF != (camFocusedBF = section.mustHitSection)) {
result.events.push({
time: curTime,
type: CAM_MOVEMENT,
params: [camFocusedBF ? 1 : 0]
});
}
if (camFocusedBF != (camFocusedBF = section.mustHitSection)) {
result.events.push({
time: curTime,
type: CAM_MOVEMENT,
params: [camFocusedBF ? 1 : 0]
});
}
if (section.sectionNotes != null) for(note in section.sectionNotes) {
if (note[1] < 0) continue;
if (section.sectionNotes != null) for(note in section.sectionNotes) {
if (note[1] < 0) continue;
var daStrumTime:Float = note[0];
var daNoteData:Int = Std.int(note[1] % 8);
var daNoteType:Int = Std.int(note[1] / 8);
var gottaHitNote:Bool = daNoteData >= 4 ? !section.mustHitSection : section.mustHitSection;
var daStrumTime:Float = note[0];
var daNoteData:Int = Std.int(note[1] % 8);
var daNoteType:Int = Std.int(note[1] / 8);
var gottaHitNote:Bool = daNoteData >= 4 ? !section.mustHitSection : section.mustHitSection;
if (note.length > 2) {
if (note[3] is Int)
daNoteType = Chart.addNoteType(result, data.noteTypes[Std.int(note[3])-1]);
else if (note[3] is String)
daNoteType = Chart.addNoteType(result, note[3]);
} else {
daNoteType = Chart.addNoteType(result, data.noteTypes[daNoteType-1]);
}
if (note.length > 2) {
if (note[3] is Int)
daNoteType = Chart.addNoteType(result, data.noteTypes[Std.int(note[3])-1]);
else if (note[3] is String)
daNoteType = Chart.addNoteType(result, note[3]);
} else {
daNoteType = Chart.addNoteType(result, data.noteTypes[daNoteType-1]);
}
result.strumLines[gottaHitNote ? 1 : 0].notes.push({
time: daStrumTime,
id: daNoteData % 4,
type: daNoteType,
sLen: note[2]
});
}
result.strumLines[gottaHitNote ? 1 : 0].notes.push({
time: daStrumTime,
id: daNoteData % 4,
type: daNoteType,
sLen: note[2]
});
}
if (section.changeBPM && section.bpm != curBPM) {
curCrochet = ((60 / (curBPM = section.bpm)) * 1000);
if (section.changeBPM && section.bpm != curBPM) {
curCrochet = ((60 / (curBPM = section.bpm)) * 1000);
result.events.push({
time: curTime,
type: BPM_CHANGE,
params: [section.bpm]
});
}
result.events.push({
time: curTime,
type: BPM_CHANGE,
params: [section.bpm]
});
}
curTime += curCrochet * beatsPerMesure;
}
}
curTime += curCrochet * beatsPerMesure;
}
}
}
typedef SwagSong =
{
+143 -143
View File
@@ -13,42 +13,42 @@ import sys.FileSystem;
using StringTools;
class Chart {
public static function loadChartMeta(songName:String, difficulty:String = "normal", fromMods:Bool = true) {
var metaPath = Paths.file('songs/${songName.toLowerCase()}/meta.json');
var metaDiffPath = Paths.file('songs/${songName.toLowerCase()}/meta-${difficulty.toLowerCase()}.json');
public static function loadChartMeta(songName:String, difficulty:String = "normal", fromMods:Bool = true) {
var metaPath = Paths.file('songs/${songName.toLowerCase()}/meta.json');
var metaDiffPath = Paths.file('songs/${songName.toLowerCase()}/meta-${difficulty.toLowerCase()}.json');
var data:ChartMetaData = null;
var fromMods:Bool = fromMods;
for(path in [metaDiffPath, metaPath]) {
if (Assets.exists(path)) {
fromMods = Paths.assetsTree.existsSpecific(path, "TEXT", MODS);
try {
data = Json.parse(Assets.getText(path));
} catch(e) {
Logs.trace('Failed to load song metadata for ${songName} ($path): ${Std.string(e)}', ERROR);
}
if (data != null) break;
}
}
var data:ChartMetaData = null;
var fromMods:Bool = fromMods;
for(path in [metaDiffPath, metaPath]) {
if (Assets.exists(path)) {
fromMods = Paths.assetsTree.existsSpecific(path, "TEXT", MODS);
try {
data = Json.parse(Assets.getText(path));
} catch(e) {
Logs.trace('Failed to load song metadata for ${songName} ($path): ${Std.string(e)}', ERROR);
}
if (data != null) break;
}
}
if (data == null)
data = {
name: songName,
bpm: 100
};
data.setFieldDefault("name", songName);
data.setFieldDefault("beatsPerMesure", 4);
data.setFieldDefault("stepsPerBeat", 4);
data.setFieldDefault("needsVoices", true);
data.setFieldDefault("icon", "face");
data.setFieldDefault("difficulties", []);
data.setFieldDefault("coopAllowed", false);
data.setFieldDefault("opponentModeAllowed", false);
data.setFieldDefault("displayName", data.name);
data.setFieldDefault("parsedColor", data.color.getColorFromDynamic());
if (data == null)
data = {
name: songName,
bpm: 100
};
data.setFieldDefault("name", songName);
data.setFieldDefault("beatsPerMesure", 4);
data.setFieldDefault("stepsPerBeat", 4);
data.setFieldDefault("needsVoices", true);
data.setFieldDefault("icon", "face");
data.setFieldDefault("difficulties", []);
data.setFieldDefault("coopAllowed", false);
data.setFieldDefault("opponentModeAllowed", false);
data.setFieldDefault("displayName", data.name);
data.setFieldDefault("parsedColor", data.color.getColorFromDynamic());
if (data.difficulties.length <= 0) {
data.difficulties = [for(f in Paths.getFolderContent('songs/${songName.toLowerCase()}/charts/', false, !fromMods)) if (Path.extension(f = f.toUpperCase()) == "JSON") Path.withoutExtension(f)];
if (data.difficulties.length <= 0) {
data.difficulties = [for(f in Paths.getFolderContent('songs/${songName.toLowerCase()}/charts/', false, !fromMods)) if (Path.extension(f = f.toUpperCase()) == "JSON") Path.withoutExtension(f)];
if (data.difficulties.length == 3) {
var hasHard = false, hasNormal = false, hasEasy = false;
for(d in data.difficulties) {
@@ -64,133 +64,133 @@ class Chart {
data.difficulties[2] = "HARD";
}
}
}
if (data.difficulties.length <= 0)
data.difficulties.push("CHART MISSING");
}
if (data.difficulties.length <= 0)
data.difficulties.push("CHART MISSING");
return data;
}
return data;
}
public static function parse(songName:String, difficulty:String = "normal"):ChartData {
var chartPath = Paths.chart(songName, difficulty);
var base:ChartData = {
strumLines: [],
noteTypes: [],
events: [],
meta: {
name: null
},
scrollSpeed: 2,
stage: "stage",
codenameChart: true,
fromMods: Paths.assetsTree.existsSpecific(chartPath, "TEXT", MODS)
};
public static function parse(songName:String, difficulty:String = "normal"):ChartData {
var chartPath = Paths.chart(songName, difficulty);
var base:ChartData = {
strumLines: [],
noteTypes: [],
events: [],
meta: {
name: null
},
scrollSpeed: 2,
stage: "stage",
codenameChart: true,
fromMods: Paths.assetsTree.existsSpecific(chartPath, "TEXT", MODS)
};
if (!Assets.exists(chartPath)) {
Logs.trace('Chart for song ${songName} ($difficulty) at "$chartPath" was not found.', ERROR, RED);
return base;
}
var data:Dynamic = null;
try {
data = Json.parse(Assets.getText(chartPath));
} catch(e) {
Logs.trace('Could not parse chart for song ${songName} ($difficulty): ${Std.string(e)}', ERROR, RED);
}
if (!Assets.exists(chartPath)) {
Logs.trace('Chart for song ${songName} ($difficulty) at "$chartPath" was not found.', ERROR, RED);
return base;
}
var data:Dynamic = null;
try {
data = Json.parse(Assets.getText(chartPath));
} catch(e) {
Logs.trace('Could not parse chart for song ${songName} ($difficulty): ${Std.string(e)}', ERROR, RED);
}
/**
* CHART CONVERSION
*/
#if REGION
if (Reflect.hasField(data, "codenameChart") && Reflect.field(data, "codenameChart") == true) {
// codename chart
base = data;
} else {
// base game chart
BaseGameParser.parse(data, base);
}
#end
/**
* CHART CONVERSION
*/
#if REGION
if (Reflect.hasField(data, "codenameChart") && Reflect.field(data, "codenameChart") == true) {
// codename chart
base = data;
} else {
// base game chart
BaseGameParser.parse(data, base);
}
#end
if (base.meta == null)
base.meta = loadChartMeta(songName, difficulty, base.fromMods);
else {
var loadedMeta = loadChartMeta(songName, difficulty, base.fromMods);
for(field in Reflect.fields(base.meta)) {
var f = Reflect.field(base.meta, field);
if (f != null)
Reflect.setField(loadedMeta, field, f);
}
base.meta = loadedMeta;
}
return base;
}
if (base.meta == null)
base.meta = loadChartMeta(songName, difficulty, base.fromMods);
else {
var loadedMeta = loadChartMeta(songName, difficulty, base.fromMods);
for(field in Reflect.fields(base.meta)) {
var f = Reflect.field(base.meta, field);
if (f != null)
Reflect.setField(loadedMeta, field, f);
}
base.meta = loadedMeta;
}
return base;
}
public static function addNoteType(chart:ChartData, noteTypeName:String):Int {
switch(noteTypeName.trim()) {
case "Default Note" | null | "":
return 0;
default:
var index = chart.noteTypes.indexOf(noteTypeName);
if (index > -1)
return index+1;
chart.noteTypes.push(noteTypeName);
return chart.noteTypes.length;
}
}
public static function addNoteType(chart:ChartData, noteTypeName:String):Int {
switch(noteTypeName.trim()) {
case "Default Note" | null | "":
return 0;
default:
var index = chart.noteTypes.indexOf(noteTypeName);
if (index > -1)
return index+1;
chart.noteTypes.push(noteTypeName);
return chart.noteTypes.length;
}
}
/**
* Saves the chart to the specific song folder path.
* @param songFolderPath Path to the song folder (ex: `mods/your mod/songs/song/`)
* @param chart Chart to save
* @param difficulty Name of the difficulty
* @param saveSettings
* @return Filtered chart used for saving.
*/
public static function save(songFolderPath:String, chart:ChartData, difficulty:String = "normal", ?saveSettings:ChartSaveSettings):ChartData {
if (saveSettings == null) saveSettings = {};
/**
* Saves the chart to the specific song folder path.
* @param songFolderPath Path to the song folder (ex: `mods/your mod/songs/song/`)
* @param chart Chart to save
* @param difficulty Name of the difficulty
* @param saveSettings
* @return Filtered chart used for saving.
*/
public static function save(songFolderPath:String, chart:ChartData, difficulty:String = "normal", ?saveSettings:ChartSaveSettings):ChartData {
if (saveSettings == null) saveSettings = {};
var filteredChart = filterChartForSaving(chart, saveSettings.saveMetaInChart);
var meta = filteredChart.meta;
var filteredChart = filterChartForSaving(chart, saveSettings.saveMetaInChart);
var meta = filteredChart.meta;
// idk how null reacts to it so better be sure
// idk how null reacts to it so better be sure
#if sys
if (!FileSystem.exists('${songFolderPath}\\charts\\'))
FileSystem.createDirectory('${songFolderPath}\\charts\\');
#if sys
if (!FileSystem.exists('${songFolderPath}\\charts\\'))
FileSystem.createDirectory('${songFolderPath}\\charts\\');
var chartPath = '${songFolderPath}\\charts\\${difficulty.trim()}.json';
var metaPath = '${songFolderPath}\\meta.json';
var chartPath = '${songFolderPath}\\charts\\${difficulty.trim()}.json';
var metaPath = '${songFolderPath}\\meta.json';
File.saveContent(chartPath, Json.stringify(filteredChart, null, saveSettings.prettyPrint == true ? "\t" : null));
File.saveContent(chartPath, Json.stringify(filteredChart, null, saveSettings.prettyPrint == true ? "\t" : null));
if (saveSettings.overrideExistingMeta == true || !FileSystem.exists(metaPath))
File.saveContent(metaPath, Json.stringify(meta, null, saveSettings.prettyPrint == true ? "\t" : null));
#end
return filteredChart;
}
if (saveSettings.overrideExistingMeta == true || !FileSystem.exists(metaPath))
File.saveContent(metaPath, Json.stringify(meta, null, saveSettings.prettyPrint == true ? "\t" : null));
#end
return filteredChart;
}
public static function filterChartForSaving(chart:ChartData, ?saveMetaInChart:Null<Bool>):ChartData {
var data = Reflect.copy(chart); // make a copy of the chart to leave the OG intact
if (saveMetaInChart != true) {
data.meta = null;
} else {
data.meta = Reflect.copy(chart.meta); // also make a copy of the metadata to leave the OG intact.
if (data.meta != null) data.meta.parsedColor = null;
}
public static function filterChartForSaving(chart:ChartData, ?saveMetaInChart:Null<Bool>):ChartData {
var data = Reflect.copy(chart); // make a copy of the chart to leave the OG intact
if (saveMetaInChart != true) {
data.meta = null;
} else {
data.meta = Reflect.copy(chart.meta); // also make a copy of the metadata to leave the OG intact.
if (data.meta != null) data.meta.parsedColor = null;
}
data.fromMods = null;
data.fromMods = null;
var sortedData:Dynamic = {};
for(f in Reflect.fields(data)) {
var v = Reflect.field(data, f);
if (v != null)
Reflect.setField(sortedData, f, v);
}
return sortedData;
}
var sortedData:Dynamic = {};
for(f in Reflect.fields(data)) {
var v = Reflect.field(data, f);
if (v != null)
Reflect.setField(sortedData, f, v);
}
return sortedData;
}
}
typedef ChartSaveSettings = {
var ?overrideExistingMeta:Bool;
var ?saveMetaInChart:Bool;
var ?prettyPrint:Bool;
var ?overrideExistingMeta:Bool;
var ?saveMetaInChart:Bool;
var ?prettyPrint:Bool;
}
+72 -72
View File
@@ -3,102 +3,102 @@ package funkin.chart;
import flixel.util.FlxColor;
typedef ChartData = {
public var strumLines:Array<ChartStrumLine>;
public var events:Array<ChartEvent>;
public var meta:ChartMetaData;
public var codenameChart:Bool;
public var stage:String;
public var scrollSpeed:Float;
public var noteTypes:Array<String>;
public var strumLines:Array<ChartStrumLine>;
public var events:Array<ChartEvent>;
public var meta:ChartMetaData;
public var codenameChart:Bool;
public var stage:String;
public var scrollSpeed:Float;
public var noteTypes:Array<String>;
public var ?fromMods:Bool;
public var ?fromMods:Bool;
}
typedef ChartMetaData = {
public var name:String;
public var ?bpm:Float;
public var ?displayName:String;
public var ?beatsPerMesure:Float;
public var ?stepsPerBeat:Float;
public var ?needsVoices:Bool;
public var ?icon:String;
public var ?color:Dynamic;
public var name:String;
public var ?bpm:Float;
public var ?displayName:String;
public var ?beatsPerMesure:Float;
public var ?stepsPerBeat:Float;
public var ?needsVoices:Bool;
public var ?icon:String;
public var ?color:Dynamic;
public var ?difficulties:Array<String>;
public var ?coopAllowed:Bool;
public var ?opponentModeAllowed:Bool;
// NOT TO BE EXPORTED
// NOT TO BE EXPORTED
public var ?parsedColor:FlxColor;
}
typedef ChartStrumLine = {
var characters:Array<String>;
var type:ChartStrumLineType;
var notes:Array<ChartNote>;
var position:String;
var ?strumLinePos:Float; // 0.25 = default opponent pos, 0.75 = default boyfriend pos
var ?visible:Null<Bool>;
var characters:Array<String>;
var type:ChartStrumLineType;
var notes:Array<ChartNote>;
var position:String;
var ?strumLinePos:Float; // 0.25 = default opponent pos, 0.75 = default boyfriend pos
var ?visible:Null<Bool>;
}
typedef ChartNote = {
var time:Float; // time at which the note will be hit (ms)
var id:Int; // strum id of the note
var type:Int; // type (int) of the note
var sLen:Float; // sustain length of the note (ms)
var time:Float; // time at which the note will be hit (ms)
var id:Int; // strum id of the note
var type:Int; // type (int) of the note
var sLen:Float; // sustain length of the note (ms)
}
typedef ChartEvent = {
var time:Float;
var type:ChartEventType;
var params:Array<Dynamic>;
var time:Float;
var type:ChartEventType;
var params:Array<Dynamic>;
}
@:enum
abstract ChartStrumLineType(Int) from Int to Int {
/**
* STRUMLINE IS MARKED AS OPPONENT - WILL BE PLAYED BY CPU, OR PLAYED BY PLAYER IF OPPONENT MODE IS ON
*/
var OPPONENT = 0;
/**
* STRUMLINE IS MARKED AS PLAYER - WILL BE PLAYED AS PLAYER, OR PLAYED AS CPU IF OPPONENT MODE IS ON
*/
var PLAYER = 1;
/**
* STRUMLINE IS MARKED AS ADDITIONAL - WILL BE PLAYED AS CPU EVEN IF OPPONENT MODE IS ENABLED
*/
var ADDITIONAL = 2;
/**
* STRUMLINE IS MARKED AS OPPONENT - WILL BE PLAYED BY CPU, OR PLAYED BY PLAYER IF OPPONENT MODE IS ON
*/
var OPPONENT = 0;
/**
* STRUMLINE IS MARKED AS PLAYER - WILL BE PLAYED AS PLAYER, OR PLAYED AS CPU IF OPPONENT MODE IS ON
*/
var PLAYER = 1;
/**
* STRUMLINE IS MARKED AS ADDITIONAL - WILL BE PLAYED AS CPU EVEN IF OPPONENT MODE IS ENABLED
*/
var ADDITIONAL = 2;
}
@:enum
abstract ChartEventType(Int) from Int to Int {
/**
* CUSTOM EVENT
* Params:
* - Function Name (String)
* - Function Parameters...
*/
var CUSTOM = -1;
/**
* NO EVENT, MADE FOR UNKNOWN EVENTS / EVENTS THAT CANNOT BE PARSED
*/
var NONE = 0;
/**
* CAMERA MOVEMENT EVENT
* Params:
* - Target Strumline ID (Int)
*/
var CAM_MOVEMENT = 1;
/**
* CUSTOM EVENT
* Params:
* - Function Name (String)
* - Function Parameters...
*/
var CUSTOM = -1;
/**
* NO EVENT, MADE FOR UNKNOWN EVENTS / EVENTS THAT CANNOT BE PARSED
*/
var NONE = 0;
/**
* CAMERA MOVEMENT EVENT
* Params:
* - Target Strumline ID (Int)
*/
var CAM_MOVEMENT = 1;
/**
* BPM CHANGE EVENT
* Params:
* - Target BPM (Float)
*/
var BPM_CHANGE = 2;
/**
* ALT ANIM TOGGLE
* Params:
* - Strum Line which is going to be toggled (Int)
* - Whenever its going to be toggled or not (Bool)
*/
var ALT_ANIM_TOGGLE = 3;
/**
* BPM CHANGE EVENT
* Params:
* - Target BPM (Float)
*/
var BPM_CHANGE = 2;
/**
* ALT ANIM TOGGLE
* Params:
* - Strum Line which is going to be toggled (Int)
* - Whenever its going to be toggled or not (Bool)
*/
var ALT_ANIM_TOGGLE = 3;
}
+13 -13
View File
@@ -4,19 +4,19 @@ package funkin.cutscenes;
* Substate made for cutscenes.
*/
class Cutscene extends MusicBeatSubstate {
var __callback:Void->Void;
var game:PlayState = PlayState.instance;
var __callback:Void->Void;
var game:PlayState = PlayState.instance;
public function new(callback:Void->Void) {
super();
__callback = callback;
}
public override function update(elapsed:Float) {
super.update(elapsed);
}
public function new(callback:Void->Void) {
super();
__callback = callback;
}
public override function update(elapsed:Float) {
super.update(elapsed);
}
public override function close() {
__callback();
super.close();
}
public override function close() {
__callback();
super.close();
}
}
+61 -61
View File
@@ -9,78 +9,78 @@ import funkin.scripting.Script;
* To add cutscenes to your songs, add a `cutscene.hx` file in your song's directory (ex: `songs/song/cutscene.hx`)
*/
class ScriptedCutscene extends Cutscene {
var script:Script;
var script:Script;
var scriptPath:String;
public function new(scriptPath:String, callback:Void->Void) {
super(callback);
var scriptPath:String;
public function new(scriptPath:String, callback:Void->Void) {
super(callback);
script = Script.create(this.scriptPath = scriptPath);
script.setPublicMap(PlayState.instance.scripts.publicVariables);
script.setParent(this);
script.load();
}
script = Script.create(this.scriptPath = scriptPath);
script.setPublicMap(PlayState.instance.scripts.publicVariables);
script.setParent(this);
script.load();
}
public override function create() {
super.create();
trace("fuck");
script.call("create");
if (Std.isOfType(script, DummyScript)) {
Logs.trace('Could not find script for scripted cutscene at ${scriptPath}', ERROR, RED);
close();
}
}
public override function create() {
super.create();
trace("fuck");
script.call("create");
if (Std.isOfType(script, DummyScript)) {
Logs.trace('Could not find script for scripted cutscene at ${scriptPath}', ERROR, RED);
close();
}
}
public override function update(elapsed:Float) {
script.call("update", [elapsed]);
super.update(elapsed);
script.call("postUpdate", [elapsed]);
}
public override function update(elapsed:Float) {
script.call("update", [elapsed]);
super.update(elapsed);
script.call("postUpdate", [elapsed]);
}
public override function beatHit(curBeat:Int) {
super.beatHit(curBeat);
script.call("beatHit", [curBeat]);
}
public override function beatHit(curBeat:Int) {
super.beatHit(curBeat);
script.call("beatHit", [curBeat]);
}
public override function stepHit(curStep:Int) {
super.stepHit(curStep);
script.call("stepHit", [curStep]);
}
public override function stepHit(curStep:Int) {
super.stepHit(curStep);
script.call("stepHit", [curStep]);
}
public override function destroy() {
script.call("destroy");
super.destroy();
}
public override function destroy() {
script.call("destroy");
super.destroy();
}
// VIDEOS
#if REGION
public function startVideo(path:String, ?callback:Void->Void) {
persistentDraw = false;
openSubState(new VideoCutscene(path, function() {
if (callback != null)
callback();
}));
}
// VIDEOS
#if REGION
public function startVideo(path:String, ?callback:Void->Void) {
persistentDraw = false;
openSubState(new VideoCutscene(path, function() {
if (callback != null)
callback();
}));
}
public var isVideoPlaying(get, null):Bool;
public var isVideoPlaying(get, null):Bool;
private inline function get_isVideoPlaying()
return subState is VideoCutscene;
#end
private inline function get_isVideoPlaying()
return subState is VideoCutscene;
#end
// DIALOGUE
#if REGION
public function startDialogue(path:String, ?callback:Void->Void) {
persistentDraw = true;
openSubState(new VideoCutscene(path, function() {
if (callback != null)
callback();
}));
}
// DIALOGUE
#if REGION
public function startDialogue(path:String, ?callback:Void->Void) {
persistentDraw = true;
openSubState(new VideoCutscene(path, function() {
if (callback != null)
callback();
}));
}
public var isDialoguePlaying(get, null):Bool;
public var isDialoguePlaying(get, null):Bool;
private inline function get_isDialoguePlaying()
return subState is DialogueCutscene;
#end
private inline function get_isDialoguePlaying()
return subState is DialogueCutscene;
#end
}
+39 -39
View File
@@ -5,52 +5,52 @@ package funkin.cutscenes;
* Substate made for video cutscenes. To use it in a scripted cutscene, call `startVideo`.
*/
class VideoCutscene extends Cutscene {
var path:String;
var localPath:String;
var path:String;
var localPath:String;
#if VIDEO_CUTSCENES
var video:MP4Handler;
var videoSprite:FlxSprite;
#end
var cutsceneCamera:FlxCamera;
#if VIDEO_CUTSCENES
var video:MP4Handler;
var videoSprite:FlxSprite;
#end
var cutsceneCamera:FlxCamera;
public function new(path:String, callback:Void->Void) {
super(callback);
localPath = Assets.getPath(this.path = path);
}
public function new(path:String, callback:Void->Void) {
super(callback);
localPath = Assets.getPath(this.path = path);
}
public override function create() {
super.create();
public override function create() {
super.create();
cutsceneCamera = new FlxCamera();
cutsceneCamera.bgColor = 0;
FlxG.cameras.add(cutsceneCamera, false);
cutsceneCamera = new FlxCamera();
cutsceneCamera.bgColor = 0;
FlxG.cameras.add(cutsceneCamera, false);
#if VIDEO_CUTSCENES
video = new MP4Handler();
video.finishCallback = close;
video.canvasWidth = cutsceneCamera.width;
video.canvasHeight = cutsceneCamera.height;
#if VIDEO_CUTSCENES
video = new MP4Handler();
video.finishCallback = close;
video.canvasWidth = cutsceneCamera.width;
video.canvasHeight = cutsceneCamera.height;
videoSprite = new FlxSprite();
videoSprite.cameras = [cutsceneCamera];
videoSprite.antialiasing = true;
add(videoSprite);
videoSprite = new FlxSprite();
videoSprite.cameras = [cutsceneCamera];
videoSprite.antialiasing = true;
add(videoSprite);
video.playMP4(localPath, false, videoSprite);
#end
video.playMP4(localPath, false, videoSprite);
#end
cameras = [cutsceneCamera];
}
cameras = [cutsceneCamera];
}
public override function update(elapsed:Float) {
super.update(elapsed);
#if !VIDEO_CUTSCENES
close();
#end
}
public override function destroy() {
FlxG.cameras.remove(cutsceneCamera, true);
super.destroy();
}
public override function update(elapsed:Float) {
super.update(elapsed);
#if !VIDEO_CUTSCENES
close();
#end
}
public override function destroy() {
FlxG.cameras.remove(cutsceneCamera, true);
super.destroy();
}
}
+91 -91
View File
@@ -6,113 +6,113 @@ import flixel.math.FlxPoint;
import haxe.xml.Access;
class DialogueBox extends FunkinSprite {
public var dialogueBoxData:Access;
public var positions:Map<String, CharPosDef> = [];
public var dialogueBoxData:Access;
public var positions:Map<String, CharPosDef> = [];
public var textTypeSFX:String = Paths.sound('dialogue/text');
public var nextSFX:String = Paths.sound('dialogue/next');
public var textTypeSFX:String = Paths.sound('dialogue/text');
public var nextSFX:String = Paths.sound('dialogue/next');
public var text:FlxTypeText;
public var text:FlxTypeText;
public function new(name:String) {
super();
try {
dialogueBoxData = new Access(Xml.parse(Assets.getText(Paths.xml('dialogue/boxes/$name'))).firstElement());
public function new(name:String) {
super();
try {
dialogueBoxData = new Access(Xml.parse(Assets.getText(Paths.xml('dialogue/boxes/$name'))).firstElement());
loadSprite(Paths.image('dialogue/boxes/${dialogueBoxData.getAtt('sprite').getDefault(name)}'));
loadSprite(Paths.image('dialogue/boxes/${dialogueBoxData.getAtt('sprite').getDefault(name)}'));
for(anim in dialogueBoxData.nodes.anim) {
if (!anim.has.name) continue;
XMLUtil.addXMLAnimation(this, anim);
}
for(anim in dialogueBoxData.nodes.anim) {
if (!anim.has.name) continue;
XMLUtil.addXMLAnimation(this, anim);
}
for(pos in dialogueBoxData.nodes.charpos) {
if (!pos.has.name) continue;
positions[pos.att.name] = {
x: pos.has.x ? Std.parseFloat(pos.att.x).getDefault(0) : 0,
y: pos.has.y ? Std.parseFloat(pos.att.y).getDefault(0) : 0,
flipBubble: pos.getAtt('flipBubble') == "true"
};
}
for(pos in dialogueBoxData.nodes.charpos) {
if (!pos.has.name) continue;
positions[pos.att.name] = {
x: pos.has.x ? Std.parseFloat(pos.att.x).getDefault(0) : 0,
y: pos.has.y ? Std.parseFloat(pos.att.y).getDefault(0) : 0,
flipBubble: pos.getAtt('flipBubble') == "true"
};
}
if (dialogueBoxData.has.textSound) textTypeSFX = Paths.sound(dialogueBoxData.att.textSound);
if (dialogueBoxData.has.nextSound) nextSFX = Paths.sound(dialogueBoxData.att.nextSound);
if (dialogueBoxData.has.textSound) textTypeSFX = Paths.sound(dialogueBoxData.att.textSound);
if (dialogueBoxData.has.nextSound) nextSFX = Paths.sound(dialogueBoxData.att.nextSound);
antialiasing = dialogueBoxData.getAtt("antialiasing").getDefault("true") == "true";
screenCenter(X);
y = FlxG.height - height;
if (dialogueBoxData.has.x) x += Std.parseFloat(dialogueBoxData.att.x).getDefault(0);
if (dialogueBoxData.has.y) y += Std.parseFloat(dialogueBoxData.att.y).getDefault(0);
visible = false;
antialiasing = dialogueBoxData.getAtt("antialiasing").getDefault("true") == "true";
screenCenter(X);
y = FlxG.height - height;
if (dialogueBoxData.has.x) x += Std.parseFloat(dialogueBoxData.att.x).getDefault(0);
if (dialogueBoxData.has.y) y += Std.parseFloat(dialogueBoxData.att.y).getDefault(0);
visible = false;
var textNode = dialogueBoxData.node.text;
if (textNode == null)
throw "The dialog box XML requires one text element.";
text = new FlxTypeText(
textNode.has.x ? Std.parseFloat(textNode.att.x).getDefault(0) : 0,
FlxG.height - (textNode.has.y ? Std.parseFloat(textNode.att.y).getDefault(0) : 0),
textNode.has.width ? Std.parseInt(textNode.att.width).getDefault(FlxG.width) : FlxG.width, "");
text.color = textNode.getAtt("color").getColorFromDynamic().getDefault(0xFF000000);
text.size = Std.parseInt(textNode.att.size).getDefault(20);
text.font = Paths.font('${textNode.getAtt("font").getDefault("vcr.ttf")}');
text.antialiasing = textNode.getAtt("antialiasing").getDefault("false") == "true";
text.sounds = [FlxG.sound.load(textTypeSFX)];
} catch(e) {
active = false;
Logs.trace('Couldn\'t load dialogue box "$name": ${e.toString()}', ERROR);
}
FlxG.sound.cache(nextSFX);
FlxG.sound.cache(textTypeSFX);
}
var textNode = dialogueBoxData.node.text;
if (textNode == null)
throw "The dialog box XML requires one text element.";
text = new FlxTypeText(
textNode.has.x ? Std.parseFloat(textNode.att.x).getDefault(0) : 0,
FlxG.height - (textNode.has.y ? Std.parseFloat(textNode.att.y).getDefault(0) : 0),
textNode.has.width ? Std.parseInt(textNode.att.width).getDefault(FlxG.width) : FlxG.width, "");
text.color = textNode.getAtt("color").getColorFromDynamic().getDefault(0xFF000000);
text.size = Std.parseInt(textNode.att.size).getDefault(20);
text.font = Paths.font('${textNode.getAtt("font").getDefault("vcr.ttf")}');
text.antialiasing = textNode.getAtt("antialiasing").getDefault("false") == "true";
text.sounds = [FlxG.sound.load(textTypeSFX)];
} catch(e) {
active = false;
Logs.trace('Couldn\'t load dialogue box "$name": ${e.toString()}', ERROR);
}
FlxG.sound.cache(nextSFX);
FlxG.sound.cache(textTypeSFX);
}
public function popupChar(char:DialogueCharacter) {
if (!active) return;
var pos = positions[char.positionName];
if (pos == null) return;
public function popupChar(char:DialogueCharacter) {
if (!active) return;
var pos = positions[char.positionName];
if (pos == null) return;
char.show((FlxG.width / 2) + pos.x, FlxG.height - pos.y);
}
char.show((FlxG.width / 2) + pos.x, FlxG.height - pos.y);
}
private var __nextText:String;
private var __speed:Float;
public function playBubbleAnim(bubble:String, text:String, speed:Float = 0.05) {
this.__nextText = text;
this.__speed = speed;
this.text.resetText(text);
FlxG.sound.play(nextSFX);
if (hasAnimation('$bubble-open'))
playAnim('$bubble-open', true);
else {
playAnim(bubble);
setText(__nextText, __speed);
}
visible = true;
}
private var __nextText:String;
private var __speed:Float;
public function playBubbleAnim(bubble:String, text:String, speed:Float = 0.05) {
this.__nextText = text;
this.__speed = speed;
this.text.resetText(text);
FlxG.sound.play(nextSFX);
if (hasAnimation('$bubble-open'))
playAnim('$bubble-open', true);
else {
playAnim(bubble);
setText(__nextText, __speed);
}
visible = true;
}
public function setText(text:String, speed:Float = 0.02) {
this.text.delay = speed;
this.text.start(speed, true);
}
public function setText(text:String, speed:Float = 0.02) {
this.text.delay = speed;
this.text.start(speed, true);
}
public override function update(elapsed:Float) {
super.update(elapsed);
if (isAnimFinished()) {
var animName = getAnimName();
if (animName.endsWith("-open")) {
playAnim(animName.substr(0, animName.length - 5));
setText(__nextText, __speed);
}
}
}
public override function update(elapsed:Float) {
super.update(elapsed);
if (isAnimFinished()) {
var animName = getAnimName();
if (animName.endsWith("-open")) {
playAnim(animName.substr(0, animName.length - 5));
setText(__nextText, __speed);
}
}
}
public override function destroy() {
super.destroy();
positions = null;
}
public override function destroy() {
super.destroy();
positions = null;
}
}
typedef CharPosDef = {
var x:Float;
var y:Float;
var flipBubble:Bool;
var x:Float;
var y:Float;
var flipBubble:Bool;
}
@@ -4,56 +4,56 @@ import flixel.tweens.FlxTween;
import haxe.xml.Access;
class DialogueCharacter extends FunkinSprite {
public var charData:Access;
public var curTween:FlxTween;
public var curTweenContext:DialogueCharTweenContext = NONE;
public var positionName:String;
public var charData:Access;
public var curTween:FlxTween;
public var curTweenContext:DialogueCharTweenContext = NONE;
public var positionName:String;
public function new(name:String, position:String) {
super();
this.positionName = position;
try {
charData = new Access(Xml.parse(Assets.getText(Paths.xml('dialogue/characters/$name'))).firstElement());
loadSprite(Paths.image('dialogue/characters/${charData.getAtt('sprite').getDefault(name)}'));
antialiasing = charData.getAtt('antialiasing').getDefault('true') == 'true';
scale.scale(charData.has.scale ? Std.parseFloat(charData.att.scale).getDefault(1) : 1);
updateHitbox();
offset.set(
charData.has.x ? Std.parseFloat(charData.att.x).getDefault(0) : 0,
(charData.has.y ? Std.parseFloat(charData.att.y).getDefault(0) : 0) + this.height);
for(anim in charData.nodes.anim)
XMLUtil.addXMLAnimation(this, anim, true);
} catch(e) {
Logs.trace('Failed to load dialogue character $name: ${e.toString()}', ERROR);
}
visible = false;
}
public function new(name:String, position:String) {
super();
this.positionName = position;
try {
charData = new Access(Xml.parse(Assets.getText(Paths.xml('dialogue/characters/$name'))).firstElement());
loadSprite(Paths.image('dialogue/characters/${charData.getAtt('sprite').getDefault(name)}'));
antialiasing = charData.getAtt('antialiasing').getDefault('true') == 'true';
scale.scale(charData.has.scale ? Std.parseFloat(charData.att.scale).getDefault(1) : 1);
updateHitbox();
offset.set(
charData.has.x ? Std.parseFloat(charData.att.x).getDefault(0) : 0,
(charData.has.y ? Std.parseFloat(charData.att.y).getDefault(0) : 0) + this.height);
for(anim in charData.nodes.anim)
XMLUtil.addXMLAnimation(this, anim, true);
} catch(e) {
Logs.trace('Failed to load dialogue character $name: ${e.toString()}', ERROR);
}
visible = false;
}
public function show(x:Float, y:Float) {
if (curTweenContext != (curTweenContext = POPIN)) {
setPosition(x, y + 100);
if (curTween != null)
curTween.cancel();
public function show(x:Float, y:Float) {
if (curTweenContext != (curTweenContext = POPIN)) {
setPosition(x, y + 100);
if (curTween != null)
curTween.cancel();
alpha = 0;
visible = true;
alpha = 0;
visible = true;
curTween = FlxTween.tween(this, {alpha: 1, y: y}, 0.2, {ease: FlxEase.quintOut});
}
}
curTween = FlxTween.tween(this, {alpha: 1, y: y}, 0.2, {ease: FlxEase.quintOut});
}
}
public function hide() {
if (curTweenContext != (curTweenContext = POPOUT)) {
if (curTween != null)
curTween.cancel();
public function hide() {
if (curTweenContext != (curTweenContext = POPOUT)) {
if (curTween != null)
curTween.cancel();
curTween = FlxTween.tween(this, {alpha: 0, y: y + 100}, 0.2, {ease: FlxEase.quintIn});
}
}
curTween = FlxTween.tween(this, {alpha: 0, y: y + 100}, 0.2, {ease: FlxEase.quintIn});
}
}
}
enum abstract DialogueCharTweenContext(Int) {
var NONE = -1;
var POPIN = 0;
var POPOUT = 1;
var NONE = -1;
var POPIN = 0;
var POPOUT = 1;
}
+27 -27
View File
@@ -6,43 +6,43 @@ import funkin.options.TreeMenu;
import funkin.windows.WindowsAPI;
class DebugOptions extends TreeMenu {
public override function create() {
super.create();
public override function create() {
super.create();
FlxG.camera.fade(0xFF000000, 0.5, true);
FlxG.camera.fade(0xFF000000, 0.5, true);
var bg:FlxSprite = new FlxSprite(-80).loadAnimatedGraphic(Paths.image('menus/menuBGBlue'));
// bg.scrollFactor.set();
var bg:FlxSprite = new FlxSprite(-80).loadAnimatedGraphic(Paths.image('menus/menuBGBlue'));
// bg.scrollFactor.set();
bg.scale.set(1.15, 1.15);
bg.updateHitbox();
bg.screenCenter();
bg.scrollFactor.set();
bg.scrollFactor.set();
bg.antialiasing = true;
add(bg);
main = new DebugOptionsScreen();
}
main = new DebugOptionsScreen();
}
}
class DebugOptionsScreen extends OptionsScreen {
public override function new() {
super("Debug Options", "Use this menu to change debug options.");
#if windows
add(new TextOption(
"Show Console",
"Select this to show the debug console, which contains log information about the game.",
function() {
WindowsAPI.allocConsole();
}));
add(new Checkbox(
"Enable Editor SFXs",
"If checked, will play sound effects when working on editors (ex: will play sfxs when checking checkboxes...)",
"editorSFX"));
add(new Checkbox(
"Resizable Editors",
"If checked, editors will be resizable and extensible like other programs instead of zooming in upon maximization.",
"resizableEditors"));
#end
}
public override function new() {
super("Debug Options", "Use this menu to change debug options.");
#if windows
add(new TextOption(
"Show Console",
"Select this to show the debug console, which contains log information about the game.",
function() {
WindowsAPI.allocConsole();
}));
add(new Checkbox(
"Enable Editor SFXs",
"If checked, will play sound effects when working on editors (ex: will play sfxs when checking checkboxes...)",
"editorSFX"));
add(new Checkbox(
"Resizable Editors",
"If checked, editors will be resizable and extensible like other programs instead of zooming in upon maximization.",
"resizableEditors"));
#end
}
}
+149 -149
View File
@@ -5,199 +5,199 @@ import flixel.math.FlxPoint;
import flixel.effects.FlxFlicker;
class EditorPicker extends MusicBeatSubstate {
public var bg:FlxSprite;
public var bg:FlxSprite;
public var options:Array<Editor> = [
{
name: "Chart Editor",
iconID: 0,
state: funkin.editors.charter.CharterSelection
},
{
name: "Character Editor",
iconID: 1,
state: null
},
{
name: "Stage Editor",
iconID: 2,
state: null
},
{
name: "UI Debug State",
iconID: 3,
state: UIDebugState
},
{
name: "Debug Options",
iconID: 4,
state: DebugOptions
}
];
public var options:Array<Editor> = [
{
name: "Chart Editor",
iconID: 0,
state: funkin.editors.charter.CharterSelection
},
{
name: "Character Editor",
iconID: 1,
state: null
},
{
name: "Stage Editor",
iconID: 2,
state: null
},
{
name: "UI Debug State",
iconID: 3,
state: UIDebugState
},
{
name: "Debug Options",
iconID: 4,
state: DebugOptions
}
];
public var sprites:Array<EditorPickerOption> = [];
public var sprites:Array<EditorPickerOption> = [];
public var curSelected:Int = 0;
public var curSelected:Int = 0;
public var oldMousePos:FlxPoint = FlxPoint.get();
public var curMousePos:FlxPoint = FlxPoint.get();
public var oldMousePos:FlxPoint = FlxPoint.get();
public var curMousePos:FlxPoint = FlxPoint.get();
public var optionHeight:Float = 0;
public var optionHeight:Float = 0;
public var selected:Bool = false;
public var selected:Bool = false;
public var camVelocity:Float = 0;
public var camVelocity:Float = 0;
public override function create() {
super.create();
public override function create() {
super.create();
camera = new FlxCamera();
camera.bgColor = 0;
FlxG.cameras.add(camera, false);
camera = new FlxCamera();
camera.bgColor = 0;
FlxG.cameras.add(camera, false);
bg = new FlxSprite().makeGraphic(1, 1, 0xFF000000);
bg.scrollFactor.set();
bg.scale.set(FlxG.width, FlxG.height);
bg.updateHitbox();
bg.alpha = 0;
add(bg);
bg = new FlxSprite().makeGraphic(1, 1, 0xFF000000);
bg.scrollFactor.set();
bg.scale.set(FlxG.width, FlxG.height);
bg.updateHitbox();
bg.alpha = 0;
add(bg);
optionHeight = FlxG.height / options.length;
for(k=>o in options) {
var spr = new EditorPickerOption(o.name, o.iconID, optionHeight);
spr.y = k * optionHeight;
add(spr);
sprites.push(spr);
}
sprites[0].selected = true;
optionHeight = FlxG.height / options.length;
for(k=>o in options) {
var spr = new EditorPickerOption(o.name, o.iconID, optionHeight);
spr.y = k * optionHeight;
add(spr);
sprites.push(spr);
}
sprites[0].selected = true;
FlxG.mouse.getScreenPosition(camera, oldMousePos);
}
FlxG.mouse.getScreenPosition(camera, oldMousePos);
}
public override function update(elapsed:Float) {
super.update(elapsed);
public override function update(elapsed:Float) {
super.update(elapsed);
bg.alpha = CoolUtil.fpsLerp(bg.alpha, selected ? 1 : 0.5, 0.25);
bg.alpha = CoolUtil.fpsLerp(bg.alpha, selected ? 1 : 0.5, 0.25);
if (selected) {
camVelocity += FlxG.width * elapsed * 2;
camera.scroll.x += camVelocity * elapsed;
return;
}
changeSelection(-FlxG.mouse.wheel + (controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0));
if (selected) {
camVelocity += FlxG.width * elapsed * 2;
camera.scroll.x += camVelocity * elapsed;
return;
}
changeSelection(-FlxG.mouse.wheel + (controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0));
FlxG.mouse.getScreenPosition(camera, curMousePos);
if (curMousePos.x != oldMousePos.x || curMousePos.y != oldMousePos.y) {
oldMousePos.set(curMousePos.x, curMousePos.y);
curSelected = -1;
changeSelection(Std.int(curMousePos.y / optionHeight)+1);
}
FlxG.mouse.getScreenPosition(camera, curMousePos);
if (curMousePos.x != oldMousePos.x || curMousePos.y != oldMousePos.y) {
oldMousePos.set(curMousePos.x, curMousePos.y);
curSelected = -1;
changeSelection(Std.int(curMousePos.y / optionHeight)+1);
}
if (controls.ACCEPT || FlxG.mouse.justReleased) {
selected = true;
CoolUtil.playMenuSFX(CONFIRM);
if (controls.ACCEPT || FlxG.mouse.justReleased) {
selected = true;
CoolUtil.playMenuSFX(CONFIRM);
FlxTransitionableState.skipNextTransIn = true;
FlxTransitionableState.skipNextTransOut = true;
FlxTransitionableState.skipNextTransIn = true;
FlxTransitionableState.skipNextTransOut = true;
FlxG.sound.music.fadeOut(0.7, 0, function(n) {
FlxG.sound.music.stop();
});
FlxG.sound.music.fadeOut(0.7, 0, function(n) {
FlxG.sound.music.stop();
});
sprites[curSelected].flicker(function() {
if (FlxG.sound.music != null)
camera.fade(0xFF000000, 0.25, false, function() {
FlxG.switchState(Type.createInstance(options[curSelected].state, []));
});
});
}
if (controls.BACK)
close();
}
sprites[curSelected].flicker(function() {
if (FlxG.sound.music != null)
camera.fade(0xFF000000, 0.25, false, function() {
FlxG.switchState(Type.createInstance(options[curSelected].state, []));
});
});
}
if (controls.BACK)
close();
}
public function changeSelection(change:Int) {
if (change == 0) return;
public function changeSelection(change:Int) {
if (change == 0) return;
curSelected = FlxMath.wrap(curSelected + change, 0, sprites.length-1);
curSelected = FlxMath.wrap(curSelected + change, 0, sprites.length-1);
for(o in sprites)
o.selected = false;
sprites[curSelected].selected = true;
}
for(o in sprites)
o.selected = false;
sprites[curSelected].selected = true;
}
}
typedef Editor = {
var name:String;
var iconID:Int;
var state:Class<MusicBeatState>;
var name:String;
var iconID:Int;
var state:Class<MusicBeatState>;
}
class EditorPickerOption extends FlxTypedSpriteGroup<FlxSprite> {
public var iconSpr:FlxSprite;
public var label:Alphabet;
public var iconSpr:FlxSprite;
public var label:Alphabet;
public var selectionBG:FlxSprite;
public var selectionBG:FlxSprite;
public var selected:Bool = false;
public var selected:Bool = false;
public var selectionLerp:Float = 0;
public var selectionLerp:Float = 0;
public var iconRotationCycle:Float = 0;
public function new(name:String, iconID:Int, height:Float) {
super();
public var iconRotationCycle:Float = 0;
public function new(name:String, iconID:Int, height:Float) {
super();
FlxG.mouse.visible = true;
iconSpr = new FlxSprite();
iconSpr.loadGraphic(Paths.image('editors/icons'), true, 128, 128);
iconSpr.animation.add("icon", [iconID], 24, true);
iconSpr.animation.play("icon");
iconSpr.antialiasing = true;
if (height < 150) {
iconSpr.scale.set(height / 150, height / 150);
iconSpr.updateHitbox();
}
iconSpr.x = 25 + ((height - iconSpr.width) / 2);
iconSpr.y = (height - iconSpr.height) / 2;
FlxG.mouse.visible = true;
iconSpr = new FlxSprite();
iconSpr.loadGraphic(Paths.image('editors/icons'), true, 128, 128);
iconSpr.animation.add("icon", [iconID], 24, true);
iconSpr.animation.play("icon");
iconSpr.antialiasing = true;
if (height < 150) {
iconSpr.scale.set(height / 150, height / 150);
iconSpr.updateHitbox();
}
iconSpr.x = 25 + ((height - iconSpr.width) / 2);
iconSpr.y = (height - iconSpr.height) / 2;
label = new Alphabet(25 + iconSpr.width + 25, 0, name, true);
label.y = (height - label.height) / 2;
label = new Alphabet(25 + iconSpr.width + 25, 0, name, true);
label.y = (height - label.height) / 2;
selectionBG = new FlxSprite().makeGraphic(1, 1, -1);
selectionBG.scale.set(FlxG.width, height);
selectionBG.updateHitbox();
selectionBG.alpha = 0;
selectionBG = new FlxSprite().makeGraphic(1, 1, -1);
selectionBG.scale.set(FlxG.width, height);
selectionBG.updateHitbox();
selectionBG.alpha = 0;
add(selectionBG);
add(iconSpr);
add(label);
}
add(selectionBG);
add(iconSpr);
add(label);
}
public override function update(elapsed:Float) {
super.update(elapsed);
iconRotationCycle += elapsed;
public override function update(elapsed:Float) {
super.update(elapsed);
iconRotationCycle += elapsed;
selectionLerp = CoolUtil.fpsLerp(selectionLerp, selected ? 1 : 0, 0.25);
selectionLerp = CoolUtil.fpsLerp(selectionLerp, selected ? 1 : 0, 0.25);
selectionBG.alpha = (iconSpr.alpha = FlxEase.cubeOut(selectionLerp)) * 0.5;
selectionBG.x = FlxMath.lerp(-FlxG.width, 0, selectionLerp);
selectionBG.alpha = (iconSpr.alpha = FlxEase.cubeOut(selectionLerp)) * 0.5;
selectionBG.x = FlxMath.lerp(-FlxG.width, 0, selectionLerp);
label.x = FlxMath.lerp(10, 25 + iconSpr.width + 25, selectionLerp);
iconSpr.x = label.x - 25 - iconSpr.width;
iconSpr.angle = Math.sin(iconRotationCycle * 0.5) * 5;
label.x = FlxMath.lerp(10, 25 + iconSpr.width + 25, selectionLerp);
iconSpr.x = label.x - 25 - iconSpr.width;
iconSpr.angle = Math.sin(iconRotationCycle * 0.5) * 5;
scrollFactor.set(FlxMath.lerp(1, 0.1, selectionLerp), 0);
selectionBG.scrollFactor.set(0, 0);
}
scrollFactor.set(FlxMath.lerp(1, 0.1, selectionLerp), 0);
selectionBG.scrollFactor.set(0, 0);
}
public override function destroy() {
super.destroy();
}
public override function destroy() {
super.destroy();
}
public function flicker(callback:Void->Void) {
FlxFlicker.flicker(label, 0.5, Options.flashingMenu ? 0.06 : 0.15, false, false, function(t) {
callback();
});
}
public function flicker(callback:Void->Void) {
FlxFlicker.flicker(label, 0.5, Options.flashingMenu ? 0.06 : 0.15, false, false, function(t) {
callback();
});
}
}
+15 -15
View File
@@ -5,27 +5,27 @@ import flixel.addons.display.FlxBackdrop;
import funkin.options.*;
class EditorTreeMenu extends TreeMenu {
public var bg:FlxBackdrop;
public var bgType:String = "default";
public var bg:FlxBackdrop;
public var bgType:String = "default";
public override function create() {
super.create();
public override function create() {
super.create();
FlxG.camera.fade(0xFF000000, 0.5, true);
FlxG.camera.fade(0xFF000000, 0.5, true);
bg = new FlxBackdrop();
bg.loadGraphic(Paths.image('editors/bgs/${bgType}'));
bg.antialiasing = true;
add(bg);
}
bg = new FlxBackdrop();
bg.loadGraphic(Paths.image('editors/bgs/${bgType}'));
bg.antialiasing = true;
add(bg);
}
public override function exit() {
FlxG.switchState(new MainMenuState());
}
public override function update(elapsed:Float) {
super.update(elapsed);
bg.x += elapsed * 125;
bg.y += elapsed * 125;
}
public override function update(elapsed:Float) {
super.update(elapsed);
bg.x += elapsed * 125;
bg.y += elapsed * 125;
}
}
+122 -122
View File
@@ -3,132 +3,132 @@ package funkin.editors;
import funkin.editors.ui.*;
class UIDebugState extends UIState {
public override function create() {
super.create();
public override function create() {
super.create();
FlxG.mouse.useSystemCursor = FlxG.mouse.visible = true;
FlxG.mouse.useSystemCursor = FlxG.mouse.visible = true;
var bg = new FlxSprite().makeGraphic(1, 1, 0xFF444444);
bg.scale.set(FlxG.width, FlxG.height);
bg.updateHitbox();
bg.scrollFactor.set();
add(bg);
var bg = new FlxSprite().makeGraphic(1, 1, 0xFF444444);
bg.scale.set(FlxG.width, FlxG.height);
bg.updateHitbox();
bg.scrollFactor.set();
add(bg);
add(new UITopMenu([
{
label: "File",
childs: [
{
label: "New"
},
{
label: "Open"
},
{
label: "Save"
},
{
label: "Save As..."
},
null,
{
label: "Exit",
onSelect: (t) -> {FlxG.switchState(new funkin.menus.MainMenuState());}
}
]
},
{
label: "Edit"
},
{
label: "View"
},
{
label: "Help"
}
]));
add(new UITopMenu([
{
label: "File",
childs: [
{
label: "New"
},
{
label: "Open"
},
{
label: "Save"
},
{
label: "Save As..."
},
null,
{
label: "Exit",
onSelect: (t) -> {FlxG.switchState(new funkin.menus.MainMenuState());}
}
]
},
{
label: "Edit"
},
{
label: "View"
},
{
label: "Help"
}
]));
add(new UICheckbox(10, 40, "Test unchecked", false));
add(new UICheckbox(10, 70, "Test checked", true));
add(new UIButton(10, 100, "Test button", function() {
trace("Hello, World!");
}, 130, 32));
add(new UIButton(10, 140, "Warning test", function() {
openSubState(new UIWarningSubstate("Test", "This is a test message", [
{
label: "Alt. Choice",
onClick: function(t) {
trace("Alt. Choice clicked!");
}
},
{
label: "OK",
onClick: function(t) {
add(new UICheckbox(10, 40, "Test unchecked", false));
add(new UICheckbox(10, 70, "Test checked", true));
add(new UIButton(10, 100, "Test button", function() {
trace("Hello, World!");
}, 130, 32));
add(new UIButton(10, 140, "Warning test", function() {
openSubState(new UIWarningSubstate("Test", "This is a test message", [
{
label: "Alt. Choice",
onClick: function(t) {
trace("Alt. Choice clicked!");
}
},
{
label: "OK",
onClick: function(t) {
}
}
]));
}, 130, 32));
add(new UIButton(10, 180, "Warning test (Overflowing)", function() {
openSubState(new UIWarningSubstate("Test", "This is a test message", [
{
label: "Alt. Choice",
onClick: function(t) {
trace("Alt. Choice clicked!");
}
},
{
label: "OK",
onClick: function(t) {}
},
{
label: "1",
onClick: function(t) {}
},
{
label: "2",
onClick: function(t) {}
},
{
label: "3",
onClick: function(t) {}
},
{
label: "4",
onClick: function(t) {}
}
]));
}, 130, 48));
}
}
}
]));
}, 130, 32));
add(new UIButton(10, 180, "Warning test (Overflowing)", function() {
openSubState(new UIWarningSubstate("Test", "This is a test message", [
{
label: "Alt. Choice",
onClick: function(t) {
trace("Alt. Choice clicked!");
}
},
{
label: "OK",
onClick: function(t) {}
},
{
label: "1",
onClick: function(t) {}
},
{
label: "2",
onClick: function(t) {}
},
{
label: "3",
onClick: function(t) {}
},
{
label: "4",
onClick: function(t) {}
}
]));
}, 130, 48));
}
public override function update(elapsed:Float) {
super.update(elapsed);
if (FlxG.mouse.justReleasedRight) {
openContextMenu([
{
label: "Test 1",
onSelect: function(t) {
trace("Test 1 clicked");
}
},
{
label: "Test 2",
onSelect: function(t) {
trace("Test 2 clicked");
}
},
{
label: "Test 3",
childs: [
{
label: "Test 4",
onSelect: function(t) {
trace("Test 4 clicked");
}
}
]
}
]);
}
}
public override function update(elapsed:Float) {
super.update(elapsed);
if (FlxG.mouse.justReleasedRight) {
openContextMenu([
{
label: "Test 1",
onSelect: function(t) {
trace("Test 1 clicked");
}
},
{
label: "Test 2",
onSelect: function(t) {
trace("Test 2 clicked");
}
},
{
label: "Test 3",
childs: [
{
label: "Test 4",
onSelect: function(t) {
trace("Test 4 clicked");
}
}
]
}
]);
}
}
}
+37 -37
View File
@@ -6,32 +6,32 @@ import funkin.shaders.CustomShader;
import flixel.util.FlxColor;
class CharterNote extends UISprite {
var angleTween:FlxTween;
var angleTween:FlxTween;
public var selected:Bool = false;
public var selected:Bool = false;
public function new() {
super();
antialiasing = true;
loadGraphic(Paths.image('editors/charter/note'), true, 157, 154);
animation.add("note", [for(i in 0...frames.frames.length) i], 0, true);
animation.play("note");
this.setUnstretchedGraphicSize(40, 40, false);
public function new() {
super();
antialiasing = true;
loadGraphic(Paths.image('editors/charter/note'), true, 157, 154);
animation.add("note", [for(i in 0...frames.frames.length) i], 0, true);
animation.play("note");
this.setUnstretchedGraphicSize(40, 40, false);
angle = 45; // green-red inbetween
angle = 45; // green-red inbetween
cursor = BUTTON;
cursor = BUTTON;
moves = false;
}
}
public override function updateButton() {
__rect.x = x;
__rect.y = y;
__rect.width = 40;
__rect.height = 40;
UIState.state.updateRectButtonHandler(this, __rect, onHovered);
}
public override function updateButton() {
__rect.x = x;
__rect.y = y;
__rect.width = 40;
__rect.height = 40;
UIState.state.updateRectButtonHandler(this, __rect, onHovered);
}
public var step:Float;
@@ -39,27 +39,27 @@ class CharterNote extends UISprite {
public var susLength:Float;
public var type:Int;
public function updatePos(step:Float, id:Int, susLength:Float = 0, type:Int = 0) {
public function updatePos(step:Float, id:Int, susLength:Float = 0, type:Int = 0) {
this.step = step;
this.id = id;
this.susLength = susLength;
this.type = type;
x = id * 40;
y = step * 40;
x = id * 40;
y = step * 40;
if (angleTween != null) angleTween.cancel();
if (angleTween != null) angleTween.cancel();
angleTween = FlxTween.tween(this, {angle: switch(animation.curAnim.curFrame = (id % 4)) {
case 0: -90;
case 1: 180;
case 2: 0;
case 3: 90;
default: 0; // how is that even possible
}}, 2/3, {ease: function(t) {
return ((Math.sin(t * Math.PI) * 0.35) * 3 * t * Math.sqrt(1 - t)) + t;
}});
}
angleTween = FlxTween.tween(this, {angle: switch(animation.curAnim.curFrame = (id % 4)) {
case 0: -90;
case 1: 180;
case 2: 0;
case 3: 90;
default: 0; // how is that even possible
}}, 2/3, {ease: function(t) {
return ((Math.sin(t * Math.PI) * 0.35) * 3 * t * Math.sqrt(1 - t)) + t;
}});
}
public override function kill() {
if (angleTween != null) {
@@ -76,7 +76,7 @@ class CharterNote extends UISprite {
}
var __passed:Bool = false;
public override function update(elapsed:Float) {
public override function update(elapsed:Float) {
super.update(elapsed);
if (__passed != (__passed = step < Conductor.curStepFloat)) {
@@ -85,8 +85,8 @@ class CharterNote extends UISprite {
Charter.instance.hitsound.replay();
}
colorTransform.redMultiplier = colorTransform.greenMultiplier = colorTransform.blueMultiplier = selected ? 0.75 : 1;
colorTransform.redOffset = colorTransform.greenOffset = selected ? 96 : 0;
colorTransform.redMultiplier = colorTransform.greenMultiplier = colorTransform.blueMultiplier = selected ? 0.75 : 1;
colorTransform.redOffset = colorTransform.greenOffset = selected ? 96 : 0;
colorTransform.blueOffset = selected ? 168 : 0;
}
}
}
@@ -3,48 +3,48 @@ package funkin.editors.charter;
import funkin.system.Conductor;
class CharterNoteGroup extends FlxTypedGroup<CharterNote> {
var __loopSprite:CharterNote;
var i:Int = 0;
var max:Float = 0;
var __currentlyLooping:Bool = false;
var __loopSprite:CharterNote;
var i:Int = 0;
var max:Float = 0;
var __currentlyLooping:Bool = false;
public override function forEach(noteFunc:CharterNote->Void, recursive:Bool = false) {
i = 0;
__loopSprite = null;
i = 0;
__loopSprite = null;
max = FlxG.height / 70 / camera.zoom;
var oldCur = __currentlyLooping;
__currentlyLooping = true;
var oldCur = __currentlyLooping;
__currentlyLooping = true;
while(i < length) {
__loopSprite = members[i];
if (__loopSprite == null || !__loopSprite.exists) {
i++;
continue;
}
if (Math.abs(__loopSprite.step - Conductor.curStepFloat) < max)
noteFunc(__loopSprite);
i++;
}
__currentlyLooping = oldCur;
}
while(i < length) {
__loopSprite = members[i];
if (__loopSprite == null || !__loopSprite.exists) {
i++;
continue;
}
if (Math.abs(__loopSprite.step - Conductor.curStepFloat) < max)
noteFunc(__loopSprite);
i++;
}
__currentlyLooping = oldCur;
}
public override function draw() {
@:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras;
public override function draw() {
@:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras;
@:privateAccess if (cameras != null) FlxCamera._defaultCameras = cameras;
forEach((n) -> n.draw());
forEach((n) -> n.draw());
@:privateAccess FlxCamera._defaultCameras = oldDefaultCameras;
}
@:privateAccess FlxCamera._defaultCameras = oldDefaultCameras;
}
public override function update(elapsed:Float) {
@:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras;
public override function update(elapsed:Float) {
@:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras;
@:privateAccess if (cameras != null) FlxCamera._defaultCameras = cameras;
forEach((n) -> n.update(elapsed));
forEach((n) -> n.update(elapsed));
@:privateAccess FlxCamera._defaultCameras = oldDefaultCameras;
}
@:privateAccess FlxCamera._defaultCameras = oldDefaultCameras;
}
}
+27 -27
View File
@@ -3,38 +3,38 @@ package funkin.editors.ui;
import flixel.math.FlxPoint;
class UIBackdrop extends UISprite {
public override function draw() {
var __oldPos = FlxPoint.get(x, y);
var __oldScroll = FlxPoint.get(scrollFactor.x, scrollFactor.y);
public override function draw() {
var __oldPos = FlxPoint.get(x, y);
var __oldScroll = FlxPoint.get(scrollFactor.x, scrollFactor.y);
x -= camera.scroll.x * scrollFactor.x;
y -= camera.scroll.y * scrollFactor.y;
x -= camera.scroll.x * scrollFactor.x;
y -= camera.scroll.y * scrollFactor.y;
while(x > -width)
x -= width;
while(y > -height)
y -= height;
while(x > -width)
x -= width;
while(y > -height)
y -= height;
var defX = x;
var defX = x;
while(y < FlxG.height) {
while(x < FlxG.width) {
super.drawSuper();
x += width;
}
y += height;
x = defX;
}
while(y < FlxG.height) {
while(x < FlxG.width) {
super.drawSuper();
x += width;
}
y += height;
x = defX;
}
setPosition(__oldPos.x, __oldPos.y);
scrollFactor.set(__oldScroll.x, __oldScroll.y);
__oldPos.put();
__oldScroll.put();
drawMembers();
}
setPosition(__oldPos.x, __oldPos.y);
scrollFactor.set(__oldScroll.x, __oldScroll.y);
__oldPos.put();
__oldScroll.put();
drawMembers();
}
public override function destroy() {
super.destroy();
}
public override function destroy() {
super.destroy();
}
}
+31 -31
View File
@@ -3,42 +3,42 @@ package funkin.editors.ui;
import flixel.graphics.frames.FlxFrame;
class UIButton extends UISliceSprite {
public var callback:Void->Void = null;
public var callback:Void->Void = null;
public var field:UIText;
public var field:UIText;
public override function new(x:Float, y:Float, text:String, callback:Void->Void, w:Int = 120, h:Int = 32) {
super(x, y, w, h, 'editors/ui/button');
this.callback = callback;
members.push(field = new UIText(x, y, w, text));
field.borderStyle = OUTLINE;
field.borderColor = 0x88000000;
field.borderSize = 1;
field.alignment = CENTER;
field.fieldWidth = w;
public override function new(x:Float, y:Float, text:String, callback:Void->Void, w:Int = 120, h:Int = 32) {
super(x, y, w, h, 'editors/ui/button');
this.callback = callback;
members.push(field = new UIText(x, y, w, text));
field.borderStyle = OUTLINE;
field.borderColor = 0x88000000;
field.borderSize = 1;
field.alignment = CENTER;
field.fieldWidth = w;
cursor = BUTTON;
}
cursor = BUTTON;
}
public override function resize(w:Int, h:Int) {
super.resize(w, h);
if (field != null)
field.fieldWidth = w;
}
public override function resize(w:Int, h:Int) {
super.resize(w, h);
if (field != null)
field.fieldWidth = w;
}
public override function onHovered() {
super.onHovered();
if (FlxG.mouse.justReleased && callback != null)
callback();
}
public override function onHovered() {
super.onHovered();
if (FlxG.mouse.justReleased && callback != null)
callback();
}
public override function update(elapsed:Float) {
super.update(elapsed);
field.follow(this, 0, (bHeight - field.height) / 2);
}
public override function update(elapsed:Float) {
super.update(elapsed);
field.follow(this, 0, (bHeight - field.height) / 2);
}
public override function draw() {
framesOffset = hovered ? (pressed ? 18 : 9) : 0;
super.draw();
}
public override function draw() {
framesOffset = hovered ? (pressed ? 18 : 9) : 0;
super.draw();
}
}
+55 -55
View File
@@ -3,74 +3,74 @@ package funkin.editors.ui;
import funkin.ui.FunkinText;
class UICheckbox extends UISprite {
public var checked:Bool = false;
public var onChecked:Bool->Void = null;
public var checked:Bool = false;
public var onChecked:Bool->Void = null;
public var field:UIText;
public var check:FlxSprite;
public var field:UIText;
public var check:FlxSprite;
public function new(x:Float, y:Float, text:String, checked:Bool = false, w:Int = 0) {
super(x, y);
loadGraphic(Paths.image('editors/ui/checkbox'), true, 20, 20);
for(frame=>name in ["normal", "hover", "pressed", "checkmark"])
animation.add(name, [frame], 0, false);
public function new(x:Float, y:Float, text:String, checked:Bool = false, w:Int = 0) {
super(x, y);
loadGraphic(Paths.image('editors/ui/checkbox'), true, 20, 20);
for(frame=>name in ["normal", "hover", "pressed", "checkmark"])
animation.add(name, [frame], 0, false);
this.checked = checked;
this.checked = checked;
field = new UIText(x, y, w, text);
check = new FlxSprite().loadGraphicFromSprite(this);
check.animation.play("checkmark");
field = new UIText(x, y, w, text);
check = new FlxSprite().loadGraphicFromSprite(this);
check.animation.play("checkmark");
members.push(check);
members.push(field);
members.push(check);
members.push(field);
cursor = BUTTON;
}
cursor = BUTTON;
}
public override function update(elapsed:Float) {
// ANIMATION HANDLING
animation.play(hovered ? (pressed ? "pressed" : "hover") : "normal");
public override function update(elapsed:Float) {
// ANIMATION HANDLING
animation.play(hovered ? (pressed ? "pressed" : "hover") : "normal");
// CHECKMARK HANDLING
check.alpha = checked ? 1 : 0;
check.scale.x = CoolUtil.fpsLerp(check.scale.x, 1, 0.25);
check.scale.y = CoolUtil.fpsLerp(check.scale.y, 1, 0.25);
// CHECKMARK HANDLING
check.alpha = checked ? 1 : 0;
check.scale.x = CoolUtil.fpsLerp(check.scale.x, 1, 0.25);
check.scale.y = CoolUtil.fpsLerp(check.scale.y, 1, 0.25);
// POSITION HANDLING
updatePositions();
// POSITION HANDLING
updatePositions();
super.update(elapsed);
}
super.update(elapsed);
}
public inline function updatePositions() {
check.follow(this);
field.follow(this, 25, 0);
}
public inline function updatePositions() {
check.follow(this);
field.follow(this, 25, 0);
}
public override function draw() {
updatePositions();
super.draw();
}
public override function draw() {
updatePositions();
super.draw();
}
public override function onHovered() {
super.onHovered();
if (FlxG.mouse.justReleased) {
// clicked
checked = !checked;
check.scale.set(1.25, 1.25);
public override function onHovered() {
super.onHovered();
if (FlxG.mouse.justReleased) {
// clicked
checked = !checked;
check.scale.set(1.25, 1.25);
if (Options.editorSFX)
CoolUtil.playMenuSFX(checked ? CHECKED : UNCHECKED, 0.5);
if (onChecked != null)
onChecked(checked);
}
}
if (Options.editorSFX)
CoolUtil.playMenuSFX(checked ? CHECKED : UNCHECKED, 0.5);
if (onChecked != null)
onChecked(checked);
}
}
public override function updateButton() {
__rect.x = x;
__rect.y = y;
__rect.width = field.width + 30;
__rect.height = field.height > height ? field.height : height;
UIState.state.updateRectButtonHandler(this, __rect, onHovered);
}
public override function updateButton() {
__rect.x = x;
__rect.y = y;
__rect.width = field.width + 30;
__rect.height = field.height > height ? field.height : height;
UIState.state.updateRectButtonHandler(this, __rect, onHovered);
}
}
+62 -62
View File
@@ -3,55 +3,55 @@ package funkin.editors.ui;
import flixel.graphics.frames.FlxFrame;
class UISliceSprite extends UISprite {
public var bWidth:Int = 120;
public var bHeight:Int = 20;
public var framesOffset:Int = 0;
public var bWidth:Int = 120;
public var bHeight:Int = 20;
public var framesOffset:Int = 0;
public var incorporeal:Bool = false;
public function new(x:Float, y:Float, w:Int, h:Int, path:String) {
super(x, y);
public function new(x:Float, y:Float, w:Int, h:Int, path:String) {
super(x, y);
frames = CoolUtil.loadFrames(Paths.image(path));
resize(w, h);
}
frames = CoolUtil.loadFrames(Paths.image(path));
resize(w, h);
}
public override function updateButton() {
public override function updateButton() {
if (incorporeal) return;
__rect.x = x;
__rect.y = y;
__rect.width = bWidth;
__rect.height = bHeight;
UIState.state.updateRectButtonHandler(this, __rect, onHovered);
}
__rect.x = x;
__rect.y = y;
__rect.width = bWidth;
__rect.height = bHeight;
UIState.state.updateRectButtonHandler(this, __rect, onHovered);
}
public function resize(w:Int, h:Int) {
bWidth = w;
bHeight = h;
}
public function resize(w:Int, h:Int) {
bWidth = w;
bHeight = h;
}
public override function draw() {
var x:Float = this.x;
var y:Float = this.y;
public override function draw() {
var x:Float = this.x;
var y:Float = this.y;
var topleft:FlxFrame = frames.frames[framesOffset];
var top:FlxFrame = frames.frames[framesOffset + 1];
var topright:FlxFrame = frames.frames[framesOffset + 2];
var middleleft:FlxFrame = frames.frames[framesOffset + 3];
var middle:FlxFrame = frames.frames[framesOffset + 4];
var middleright:FlxFrame = frames.frames[framesOffset + 5];
var bottomleft:FlxFrame = frames.frames[framesOffset + 6];
var bottom:FlxFrame = frames.frames[framesOffset + 7];
var bottomright:FlxFrame = frames.frames[framesOffset + 8];
var topleft:FlxFrame = frames.frames[framesOffset];
var top:FlxFrame = frames.frames[framesOffset + 1];
var topright:FlxFrame = frames.frames[framesOffset + 2];
var middleleft:FlxFrame = frames.frames[framesOffset + 3];
var middle:FlxFrame = frames.frames[framesOffset + 4];
var middleright:FlxFrame = frames.frames[framesOffset + 5];
var bottomleft:FlxFrame = frames.frames[framesOffset + 6];
var bottom:FlxFrame = frames.frames[framesOffset + 7];
var bottomright:FlxFrame = frames.frames[framesOffset + 8];
@:privateAccess if (visible) {
// TOP LEFT
frame = topleft;
setPosition(x, y);
__setSize(topleft.frame.width, topleft.frame.height);
super.drawSuper();
@:privateAccess if (visible) {
// TOP LEFT
frame = topleft;
setPosition(x, y);
__setSize(topleft.frame.width, topleft.frame.height);
super.drawSuper();
// TOP
// TOP
if (bWidth > topleft.frame.width + topright.frame.width) {
frame = top;
setPosition(x + topleft.frame.width, y);
@@ -59,13 +59,13 @@ class UISliceSprite extends UISprite {
super.drawSuper();
}
// TOP RIGHT
frame = topright;
setPosition(x + bWidth - topright.frame.width, y);
__setSize(topright.frame.width, topright.frame.height);
super.drawSuper();
// TOP RIGHT
frame = topright;
setPosition(x + bWidth - topright.frame.width, y);
__setSize(topright.frame.width, topright.frame.height);
super.drawSuper();
// MIDDLE LEFT
// MIDDLE LEFT
if (bHeight > top.frame.height + bottom.frame.height) {
frame = middleleft;
setPosition(x, y + top.frame.height);
@@ -87,11 +87,11 @@ class UISliceSprite extends UISprite {
super.drawSuper();
}
// BOTTOM LEFT
frame = bottomleft;
setPosition(x, y + bHeight - bottom.frame.height);
__setSize(bottomleft.frame.width, bottomleft.frame.height);
super.drawSuper();
// BOTTOM LEFT
frame = bottomleft;
setPosition(x, y + bHeight - bottom.frame.height);
__setSize(bottomleft.frame.width, bottomleft.frame.height);
super.drawSuper();
if (bWidth > bottomleft.frame.width + bottomright.frame.width) {
// BOTTOM
@@ -101,20 +101,20 @@ class UISliceSprite extends UISprite {
super.drawSuper();
}
// BOTTOM RIGHT
frame = bottomright;
setPosition(x + bWidth - bottomright.frame.width, y + bHeight - bottom.frame.height);
__setSize(bottomright.frame.width, bottomright.frame.height);
super.drawSuper();
}
// BOTTOM RIGHT
frame = bottomright;
setPosition(x + bWidth - bottomright.frame.width, y + bHeight - bottom.frame.height);
__setSize(bottomright.frame.width, bottomright.frame.height);
super.drawSuper();
}
setPosition(x, y);
setPosition(x, y);
super.drawMembers();
}
super.drawMembers();
}
private function __setSize(Width:Float, Height:Float) {
var newScaleX:Float = Width / frameWidth;
private function __setSize(Width:Float, Height:Float) {
var newScaleX:Float = Width / frameWidth;
var newScaleY:Float = Height / frameHeight;
scale.set(newScaleX, newScaleY);
@@ -123,6 +123,6 @@ class UISliceSprite extends UISprite {
else if (Height <= 0)
scale.y = newScaleX;
updateHitbox();
}
updateHitbox();
}
}
+57 -57
View File
@@ -7,80 +7,80 @@ import openfl.ui.MouseCursor;
@:allow(funkin.editors.ui.UIState)
@:allow(funkin.editors.ui.UIUtil)
class UISprite extends FlxSprite {
public var members:Array<FlxBasic> = [];
public var members:Array<FlxBasic> = [];
private var __lastDrawCameras:Array<FlxCamera> = [];
private var __rect:FlxRect = new FlxRect();
private var __lastDrawCameras:Array<FlxCamera> = [];
private var __rect:FlxRect = new FlxRect();
private var __oldDefCams:Array<FlxCamera>;
private var __oldDefCams:Array<FlxCamera>;
public var hovered:Bool = false;
public var hoveredByChild:Bool = false;
public var pressed:Bool = false;
public var hovered:Bool = false;
public var hoveredByChild:Bool = false;
public var pressed:Bool = false;
public var hoverCallback:Void->Void = null;
public var hoverCallback:Void->Void = null;
public var cursor:MouseCursor = ARROW;
public var cursor:MouseCursor = ARROW;
public override function update(elapsed:Float) {
hovered = false;
pressed = false;
hoveredByChild = false;
public override function update(elapsed:Float) {
hovered = false;
pressed = false;
hoveredByChild = false;
super.update(elapsed);
updateButton();
super.update(elapsed);
updateButton();
@:privateAccess {
__oldDefCams = FlxCamera._defaultCameras;
FlxCamera._defaultCameras = cameras;
@:privateAccess {
__oldDefCams = FlxCamera._defaultCameras;
FlxCamera._defaultCameras = cameras;
for(m in members)
m.update(elapsed);
for(m in members)
m.update(elapsed);
FlxCamera._defaultCameras = __oldDefCams;
}
FlxCamera._defaultCameras = __oldDefCams;
}
}
}
public override function draw() {
drawSuper();
drawMembers();
}
public override function draw() {
drawSuper();
drawMembers();
}
public function drawSuper() {
super.draw();
__lastDrawCameras = [for(c in cameras) c];
}
public function drawSuper() {
super.draw();
__lastDrawCameras = [for(c in cameras) c];
}
public function drawMembers() {
@:privateAccess {
__oldDefCams = FlxCamera._defaultCameras;
FlxCamera._defaultCameras = cameras;
public function drawMembers() {
@:privateAccess {
__oldDefCams = FlxCamera._defaultCameras;
FlxCamera._defaultCameras = cameras;
for(m in members)
m.draw();
for(m in members)
m.draw();
FlxCamera._defaultCameras = __oldDefCams;
}
}
FlxCamera._defaultCameras = __oldDefCams;
}
}
public override function destroy() {
super.destroy();
members = FlxDestroyUtil.destroyArray(members);
}
public override function destroy() {
super.destroy();
members = FlxDestroyUtil.destroyArray(members);
}
public function updateButton() {
UIState.state.updateButtonHandler(this, onHovered);
}
public function updateButton() {
UIState.state.updateButtonHandler(this, onHovered);
}
/**
* Called whenever the sprite is being hovered by the mouse.
*/
public function onHovered() {
hovered = true;
if (FlxG.mouse.pressed)
pressed = true;
if (hoverCallback != null)
hoverCallback();
}
/**
* Called whenever the sprite is being hovered by the mouse.
*/
public function onHovered() {
hovered = true;
if (FlxG.mouse.pressed)
pressed = true;
if (hoverCallback != null)
hoverCallback();
}
}
+5 -5
View File
@@ -4,9 +4,9 @@ import flixel.util.FlxColor;
import funkin.ui.FunkinText;
class UIText extends FunkinText {
// PUTTING THIS HERE IN CASE IMMA MAKE FUTURE CHANGES
public function new(x, y, w, text, size:Int = 15, color:FlxColor = 0xFFFFFFFF) {
super(x, y, w, text, size, false);
this.color = color;
}
// PUTTING THIS HERE IN CASE IMMA MAKE FUTURE CHANGES
public function new(x, y, w, text, size:Int = 15, color:FlxColor = 0xFFFFFFFF) {
super(x, y, w, text, size, false);
this.color = color;
}
}
+55 -55
View File
@@ -3,74 +3,74 @@ package funkin.editors.ui;
import funkin.editors.ui.UIContextMenu.UIContextMenuOption;
class UITopMenu extends UISliceSprite {
var options:Array<UIContextMenuOption>;
public function new(options:Array<UIContextMenuOption>) {
this.options = options;
super(0, 0, FlxG.width, 25, 'editors/ui/topmenu');
scrollFactor.set(0, 0);
var options:Array<UIContextMenuOption>;
public function new(options:Array<UIContextMenuOption>) {
this.options = options;
super(0, 0, FlxG.width, 25, 'editors/ui/topmenu');
scrollFactor.set(0, 0);
var x:Int = 0;
for(o in options) {
var b = new UITopMenuButton(x, 0, this, o.label, o.childs);
x += b.bWidth;
members.push(b);
}
}
var x:Int = 0;
for(o in options) {
var b = new UITopMenuButton(x, 0, this, o.label, o.childs);
x += b.bWidth;
members.push(b);
}
}
public var anyMenuOpened:Bool = false;
public var anyMenuOpened:Bool = false;
public override function update(elapsed:Float) {
anyMenuOpened = false;
for(c in members) if (cast(c, UITopMenuButton).curMenu.contextMenuOpened()) {
anyMenuOpened = true;
break;
}
public override function update(elapsed:Float) {
anyMenuOpened = false;
for(c in members) if (cast(c, UITopMenuButton).curMenu.contextMenuOpened()) {
anyMenuOpened = true;
break;
}
super.update(elapsed);
super.update(elapsed);
bWidth = FlxG.width;
}
bWidth = FlxG.width;
}
}
class UITopMenuButton extends UISliceSprite {
public var label:UIText;
public var contextMenu:Array<UIContextMenuOption>;
public var parent:UITopMenu;
public var label:UIText;
public var contextMenu:Array<UIContextMenuOption>;
public var parent:UITopMenu;
public var curMenu:UIContextMenu = null;
public var curMenu:UIContextMenu = null;
public function new(x:Float, y:Float, parent:UITopMenu, label:String, contextMenu:Array<UIContextMenuOption>) {
super(x, y, 0, 23, "editors/ui/menu-item");
this.contextMenu = contextMenu;
this.parent = parent;
cursor = BUTTON;
public function new(x:Float, y:Float, parent:UITopMenu, label:String, contextMenu:Array<UIContextMenuOption>) {
super(x, y, 0, 23, "editors/ui/menu-item");
this.contextMenu = contextMenu;
this.parent = parent;
cursor = BUTTON;
this.label = new UIText(4, 0, 0, label);
this.label.alignment = CENTER;
bWidth = this.label.frameWidth + 8;
members.push(this.label);
}
this.label = new UIText(4, 0, 0, label);
this.label.alignment = CENTER;
bWidth = this.label.frameWidth + 8;
members.push(this.label);
}
public override function update(elapsed:Float) {
label.follow(this, 4, Std.int((bHeight - label.height) / 2));
super.update(elapsed);
public override function update(elapsed:Float) {
label.follow(this, 4, Std.int((bHeight - label.height) / 2));
super.update(elapsed);
var opened = curMenu.contextMenuOpened();
alpha = (hovered || opened) ? 1 : 0;
framesOffset = opened ? 9 : 0;
}
var opened = curMenu.contextMenuOpened();
alpha = (hovered || opened) ? 1 : 0;
framesOffset = opened ? 9 : 0;
}
public override function onHovered() {
super.onHovered();
if (hovered) {
if (curMenu.contextMenuOpened()) {
UIState.state.curContextMenu.preventOutOfBoxClickDeletion();
} else {
if (parent.anyMenuOpened || FlxG.mouse.justReleased) {
curMenu = UIState.state.openContextMenu(contextMenu, null, x, y + bHeight);
}
}
}
}
public override function onHovered() {
super.onHovered();
if (hovered) {
if (curMenu.contextMenuOpened()) {
UIState.state.curContextMenu.preventOutOfBoxClickDeletion();
} else {
if (parent.anyMenuOpened || FlxG.mouse.justReleased) {
curMenu = UIState.state.openContextMenu(contextMenu, null, x, y + bHeight);
}
}
}
}
}
+58 -58
View File
@@ -5,82 +5,82 @@ import flixel.tweens.FlxEase;
import funkin.shaders.CustomShader;
class UIWarningSubstate extends MusicBeatSubstate {
var camShaders:Array<FlxCamera> = [];
var blurShader:CustomShader = new CustomShader("engine/editorBlur");
var camShaders:Array<FlxCamera> = [];
var blurShader:CustomShader = new CustomShader("engine/editorBlur");
var title:String;
var message:String;
var buttons:Array<WarningButton>;
var title:String;
var message:String;
var buttons:Array<WarningButton>;
var titleSpr:UIText;
var messageSpr:UIText;
var titleSpr:UIText;
var messageSpr:UIText;
var warnCam:FlxCamera;
var warnCam:FlxCamera;
public override function onSubstateOpen() {
super.onSubstateOpen();
parent.persistentUpdate = false;
parent.persistentDraw = true;
}
public override function onSubstateOpen() {
super.onSubstateOpen();
parent.persistentUpdate = false;
parent.persistentDraw = true;
}
public override function create() {
for(c in FlxG.cameras.list) {
camShaders.push(c);
c.addShader(blurShader);
}
public override function create() {
for(c in FlxG.cameras.list) {
camShaders.push(c);
c.addShader(blurShader);
}
camera = warnCam = new FlxCamera();
warnCam.bgColor = 0;
warnCam.alpha = 0;
warnCam.zoom = 0.1;
FlxG.cameras.add(warnCam, false);
camera = warnCam = new FlxCamera();
warnCam.bgColor = 0;
warnCam.alpha = 0;
warnCam.zoom = 0.1;
FlxG.cameras.add(warnCam, false);
var spr = new UISliceSprite(0, 0, CoolUtil.maxInt(560, 30 + (170 * buttons.length)), 280, "editors/ui/warning-popup");
spr.x = (FlxG.width - spr.bWidth) / 2;
spr.y = (FlxG.height - spr.bHeight) / 2;
add(spr);
var spr = new UISliceSprite(0, 0, CoolUtil.maxInt(560, 30 + (170 * buttons.length)), 280, "editors/ui/warning-popup");
spr.x = (FlxG.width - spr.bWidth) / 2;
spr.y = (FlxG.height - spr.bHeight) / 2;
add(spr);
add(titleSpr = new UIText(spr.x + 25, spr.y, spr.bWidth - 50, title, 15, -1));
titleSpr.y = spr.y + ((30 - titleSpr.height) / 2);
add(titleSpr = new UIText(spr.x + 25, spr.y, spr.bWidth - 50, title, 15, -1));
titleSpr.y = spr.y + ((30 - titleSpr.height) / 2);
add(messageSpr = new UIText(spr.x + 10, spr.y + 40, spr.bWidth - 20, message, 15, -1));
add(messageSpr = new UIText(spr.x + 10, spr.y + 40, spr.bWidth - 20, message, 15, -1));
var xPos = (FlxG.width - (30 + (170 * buttons.length))) / 2;
for(k=>b in buttons) {
var button = new UIButton(xPos + 20 + (170 * k), spr.y + spr.bHeight - 40, b.label, function() {
b.onClick(this);
close();
}, 160, 30);
add(button);
}
var xPos = (FlxG.width - (30 + (170 * buttons.length))) / 2;
for(k=>b in buttons) {
var button = new UIButton(xPos + 20 + (170 * k), spr.y + spr.bHeight - 40, b.label, function() {
b.onClick(this);
close();
}, 160, 30);
add(button);
}
FlxTween.tween(camera, {alpha: 1}, 0.25, {ease: FlxEase.cubeOut});
FlxTween.tween(camera, {zoom: 1}, 0.66, {ease: FlxEase.elasticOut});
FlxTween.tween(camera, {alpha: 1}, 0.25, {ease: FlxEase.cubeOut});
FlxTween.tween(camera, {zoom: 1}, 0.66, {ease: FlxEase.elasticOut});
CoolUtil.playMenuSFX(WARNING);
}
CoolUtil.playMenuSFX(WARNING);
}
public override function destroy() {
super.destroy();
for(e in camShaders)
e.removeShader(blurShader);
public override function destroy() {
super.destroy();
for(e in camShaders)
e.removeShader(blurShader);
FlxTween.cancelTweensOf(warnCam);
FlxG.cameras.remove(warnCam);
}
FlxTween.cancelTweensOf(warnCam);
FlxG.cameras.remove(warnCam);
}
public function new(title:String, message:String, buttons:Array<WarningButton>) {
super();
this.title = title;
this.message = message;
this.buttons = buttons;
}
public function new(title:String, message:String, buttons:Array<WarningButton>) {
super();
this.title = title;
this.message = message;
this.buttons = buttons;
}
}
typedef WarningCamShader = {
var cam:FlxCamera;
var cam:FlxCamera;
}
typedef WarningButton = {
var label:String;
var onClick:UIWarningSubstate->Void;
var label:String;
var onClick:UIWarningSubstate->Void;
}
+14 -14
View File
@@ -29,20 +29,20 @@ import openfl.filters.ShaderFilter;
import openfl.Vector;
class HudCamera extends FlxCamera {
public var downscroll:Bool = false;
public override function update(elapsed:Float) {
super.update(elapsed);
flipY = downscroll;
}
public var downscroll:Bool = false;
public override function update(elapsed:Float) {
super.update(elapsed);
flipY = downscroll;
}
public override function drawPixels(?frame:FlxFrame, ?pixels:BitmapData, matrix:FlxMatrix, ?transform:ColorTransform, ?blend:BlendMode, ?smoothing:Bool = false,
?shader:FlxShader):Void
{
if (downscroll) {
matrix.scale(1, -1);
matrix.translate(0, height);
}
super.drawPixels(frame, pixels, matrix, transform, blend, smoothing, shader);
}
public override function drawPixels(?frame:FlxFrame, ?pixels:BitmapData, matrix:FlxMatrix, ?transform:ColorTransform, ?blend:BlendMode, ?smoothing:Bool = false,
?shader:FlxShader):Void
{
if (downscroll) {
matrix.scale(1, -1);
matrix.translate(0, height);
}
super.drawPixels(frame, pixels, matrix, transform, blend, smoothing, shader);
}
}
+91 -91
View File
@@ -4,112 +4,112 @@ import flixel.util.FlxSort;
import funkin.system.Conductor;
class NoteGroup extends FlxTypedGroup<Note> {
var __loopSprite:Note;
var i:Int = 0;
var __currentlyLooping:Bool = false;
var __loopSprite:Note;
var i:Int = 0;
var __currentlyLooping:Bool = false;
public function addNotes(notes:Array<Note>) {
for(e in notes) add(e);
sortNotes();
}
public function addNotes(notes:Array<Note>) {
for(e in notes) add(e);
sortNotes();
}
public function sortNotes() {
sort(function(i, n1, n2) {
if (n1.strumTime == n2.strumTime)
return n1.isSustainNote ? -1 : 1;
return FlxSort.byValues(FlxSort.ASCENDING, n1.strumTime, n2.strumTime);
});
}
public override function update(elapsed:Float) {
i = 0;
__loopSprite = null;
while(i < length) {
__loopSprite = members[i];
if (__loopSprite == null || !__loopSprite.exists || !__loopSprite.active) {
i++;
continue;
}
if (__loopSprite.strumTime - Conductor.songPosition > 1500)
break;
__loopSprite.update(elapsed);
i++;
}
}
public function sortNotes() {
sort(function(i, n1, n2) {
if (n1.strumTime == n2.strumTime)
return n1.isSustainNote ? -1 : 1;
return FlxSort.byValues(FlxSort.ASCENDING, n1.strumTime, n2.strumTime);
});
}
public override function update(elapsed:Float) {
i = 0;
__loopSprite = null;
while(i < length) {
__loopSprite = members[i];
if (__loopSprite == null || !__loopSprite.exists || !__loopSprite.active) {
i++;
continue;
}
if (__loopSprite.strumTime - Conductor.songPosition > 1500)
break;
__loopSprite.update(elapsed);
i++;
}
}
public override function draw() {
@:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras;
public override function draw() {
@:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras;
@:privateAccess if (cameras != null) FlxCamera._defaultCameras = cameras;
i = 0;
__loopSprite = null;
i = 0;
__loopSprite = null;
var oldCur = __currentlyLooping;
__currentlyLooping = true;
while(i < length) {
__loopSprite = members[i];
if (__loopSprite == null || !__loopSprite.exists || !__loopSprite.visible) {
i++;
continue;
}
if (__loopSprite.strumTime - Conductor.songPosition > 1500) break;
__loopSprite.draw();
i++;
}
__currentlyLooping = oldCur;
var oldCur = __currentlyLooping;
__currentlyLooping = true;
while(i < length) {
__loopSprite = members[i];
if (__loopSprite == null || !__loopSprite.exists || !__loopSprite.visible) {
i++;
continue;
}
if (__loopSprite.strumTime - Conductor.songPosition > 1500) break;
__loopSprite.draw();
i++;
}
__currentlyLooping = oldCur;
@:privateAccess FlxCamera._defaultCameras = oldDefaultCameras;
}
@:privateAccess FlxCamera._defaultCameras = oldDefaultCameras;
}
public override function forEach(noteFunc:Note->Void, recursive:Bool = false) {
i = 0;
__loopSprite = null;
public override function forEach(noteFunc:Note->Void, recursive:Bool = false) {
i = 0;
__loopSprite = null;
var oldCur = __currentlyLooping;
__currentlyLooping = true;
var oldCur = __currentlyLooping;
__currentlyLooping = true;
while(i < length) {
__loopSprite = members[i];
if (__loopSprite == null || !__loopSprite.exists) {
i++;
continue;
}
if (__loopSprite.strumTime - Conductor.songPosition > 1500) break;
noteFunc(__loopSprite);
i++;
}
__currentlyLooping = oldCur;
}
public override function forEachAlive(noteFunc:Note->Void, recursive:Bool = false) {
forEach(function(note) {
if (note.alive) noteFunc(note);
}, recursive);
}
while(i < length) {
__loopSprite = members[i];
if (__loopSprite == null || !__loopSprite.exists) {
i++;
continue;
}
if (__loopSprite.strumTime - Conductor.songPosition > 1500) break;
noteFunc(__loopSprite);
i++;
}
__currentlyLooping = oldCur;
}
public override function forEachAlive(noteFunc:Note->Void, recursive:Bool = false) {
forEach(function(note) {
if (note.alive) noteFunc(note);
}, recursive);
}
public override function remove(Object:Note, Splice:Bool = false):Note
{
if (members == null)
return null;
public override function remove(Object:Note, Splice:Bool = false):Note
{
if (members == null)
return null;
var index:Int = members.indexOf(Object);
var index:Int = members.indexOf(Object);
if (index < 0)
return null;
if (index < 0)
return null;
// doesnt prevent looping from breaking
if (Splice && __currentlyLooping && i >= index)
i--;
// doesnt prevent looping from breaking
if (Splice && __currentlyLooping && i >= index)
i--;
if (Splice)
{
members.splice(index, 1);
length--;
}
else
members[index] = null;
if (Splice)
{
members.splice(index, 1);
length--;
}
else
members[index] = null;
if (_memberRemoved != null)
_memberRemoved.dispatch(Object);
if (_memberRemoved != null)
_memberRemoved.dispatch(Object);
return Object;
}
return Object;
}
}
+94 -94
View File
@@ -3,114 +3,114 @@ package funkin.game;
import haxe.xml.Access;
class SplashGroup extends FlxTypedGroup<FunkinSprite> {
/**
* Whenever the splash group has successfully loaded or not.
*/
public var valid:Bool = true;
/**
* Whenever the splash group has successfully loaded or not.
*/
public var valid:Bool = true;
/**
* XML data for the note splashes.
*/
public var xml:Access;
/**
* XML data for the note splashes.
*/
public var xml:Access;
/**
* Animation names sorted by strum IDs.
* Use `getSplashAnim` to get one.
*/
public var animationNames:Array<Array<String>> = [];
/**
* Animation names sorted by strum IDs.
* Use `getSplashAnim` to get one.
*/
public var animationNames:Array<Array<String>> = [];
/**
* Creates a new Splash group
* @param path Path to the splash data (xml)
*/
public function new(path) {
super();
/**
* Creates a new Splash group
* @param path Path to the splash data (xml)
*/
public function new(path) {
super();
try {
xml = new Access(Xml.parse(Assets.getText(path)).firstElement());
try {
xml = new Access(Xml.parse(Assets.getText(path)).firstElement());
if (!xml.has.sprite) throw "The <splash> element requires a sprite attribute.";
if (!xml.has.sprite) throw "The <splash> element requires a sprite attribute.";
var splashSprite = new FunkinSprite();
splashSprite.antialiasing = true;
splashSprite.active = splashSprite.visible = false;
splashSprite.loadSprite(Paths.image(xml.att.sprite));
var splashSprite = new FunkinSprite();
splashSprite.antialiasing = true;
splashSprite.active = splashSprite.visible = false;
splashSprite.loadSprite(Paths.image(xml.att.sprite));
/**
* ANIMATIONS
*/
for(strum in xml.nodes.strum) {
var id:Null<Int> = Std.parseInt(strum.att.id);
if (id != null) {
animationNames[id] = [];
for(anim in strum.nodes.anim) {
if (!anim.has.name) continue;
XMLUtil.addXMLAnimation(splashSprite, anim, false);
animationNames[id].push(anim.att.name);
}
}
}
if (animationNames.length <= 0)
animationNames.push([]);
for(anim in xml.nodes.anim) {
if (!anim.has.name) continue;
XMLUtil.addXMLAnimation(splashSprite, anim, false);
for(a in animationNames) {
if (a == null) continue;
a.push(anim.att.name);
}
}
/**
* END OF ANIMATIONS
*/
splashSprite.animation.finishCallback = function(name) {
splashSprite.active = splashSprite.visible = false;
};
/**
* ANIMATIONS
*/
for(strum in xml.nodes.strum) {
var id:Null<Int> = Std.parseInt(strum.att.id);
if (id != null) {
animationNames[id] = [];
for(anim in strum.nodes.anim) {
if (!anim.has.name) continue;
XMLUtil.addXMLAnimation(splashSprite, anim, false);
animationNames[id].push(anim.att.name);
}
}
}
if (animationNames.length <= 0)
animationNames.push([]);
for(anim in xml.nodes.anim) {
if (!anim.has.name) continue;
XMLUtil.addXMLAnimation(splashSprite, anim, false);
for(a in animationNames) {
if (a == null) continue;
a.push(anim.att.name);
}
}
/**
* END OF ANIMATIONS
*/
splashSprite.animation.finishCallback = function(name) {
splashSprite.active = splashSprite.visible = false;
};
if (xml.has.scale) splashSprite.scale.scale(Std.parseFloat(xml.att.scale).getDefault(1));
if (xml.has.alpha) splashSprite.alpha = Std.parseFloat(xml.att.alpha).getDefault(1);
if (xml.has.antialiasing) splashSprite.antialiasing = xml.att.antialiasing == "true";
if (xml.has.scale) splashSprite.scale.scale(Std.parseFloat(xml.att.scale).getDefault(1));
if (xml.has.alpha) splashSprite.alpha = Std.parseFloat(xml.att.alpha).getDefault(1);
if (xml.has.antialiasing) splashSprite.antialiasing = xml.att.antialiasing == "true";
add(splashSprite);
add(splashSprite);
for (i in 0...7) {
// make 7 additional splashes
var spr = FunkinSprite.copyFrom(splashSprite);
spr.animation.finishCallback = function(name) {
spr.active = spr.visible = false;
};
add(spr);
}
for (i in 0...7) {
// make 7 additional splashes
var spr = FunkinSprite.copyFrom(splashSprite);
spr.animation.finishCallback = function(name) {
spr.active = spr.visible = false;
};
add(spr);
}
// immediatly draw once and put image in GPU to prevent freezes
splashSprite.draw();
} catch(e) {
Logs.trace('Couldn\'t parse splash data for "${path}": ${e.toString()}', ERROR);
valid = false;
}
// immediatly draw once and put image in GPU to prevent freezes
splashSprite.draw();
} catch(e) {
Logs.trace('Couldn\'t parse splash data for "${path}": ${e.toString()}', ERROR);
valid = false;
}
maxSize = 8;
}
maxSize = 8;
}
public function getSplashAnim(id:Int):String {
if (animationNames.length <= 0) return null;
id %= animationNames.length;
if (animationNames[id] == null) return null;
if (animationNames[id].length <= 0) return null;
return animationNames[id][FlxG.random.int(0, animationNames[id].length-1)];
}
public function getSplashAnim(id:Int):String {
if (animationNames.length <= 0) return null;
id %= animationNames.length;
if (animationNames[id] == null) return null;
if (animationNames[id].length <= 0) return null;
return animationNames[id][FlxG.random.int(0, animationNames[id].length-1)];
}
var __splash:FunkinSprite;
public function showOnStrum(strum:Strum) {
if (!valid) return null;
__splash = recycle();
var __splash:FunkinSprite;
public function showOnStrum(strum:Strum) {
if (!valid) return null;
__splash = recycle();
__splash.cameras = strum.lastDrawCameras;
__splash.setPosition(strum.x + ((strum.width - __splash.width) / 2), strum.y + ((strum.height - __splash.height) / 2));
__splash.active = __splash.visible = true;
__splash.playAnim(getSplashAnim(strum.ID), true);
__splash.scrollFactor.set(strum.scrollFactor.x, strum.scrollFactor.y);
__splash.cameras = strum.lastDrawCameras;
__splash.setPosition(strum.x + ((strum.width - __splash.width) / 2), strum.y + ((strum.height - __splash.height) / 2));
__splash.active = __splash.visible = true;
__splash.playAnim(getSplashAnim(strum.ID), true);
__splash.scrollFactor.set(strum.scrollFactor.x, strum.scrollFactor.y);
return __splash;
}
return __splash;
}
}
+39 -39
View File
@@ -2,49 +2,49 @@ package funkin.game;
class SplashHandler extends FlxTypedGroup<FunkinSprite> {
/**
* Map containing all of the splashes group.
*/
public var grpMap:Map<String, SplashGroup> = [];
/**
* Map containing all of the splashes group.
*/
public var grpMap:Map<String, SplashGroup> = [];
public function new() {
super();
}
public function new() {
super();
}
/**
* Returns a group of splashes, and creates it if it doesn't exist.
* @param path Path to the splashes XML (`Paths.xml('splashes/splash')`)
*/
public function getSplashGroup(name:String) {
if (!grpMap.exists(name)) {
var grp = new SplashGroup(Paths.xml('splashes/$name'));
grpMap.set(name, grp);
}
return grpMap.get(name);
}
/**
* Returns a group of splashes, and creates it if it doesn't exist.
* @param path Path to the splashes XML (`Paths.xml('splashes/splash')`)
*/
public function getSplashGroup(name:String) {
if (!grpMap.exists(name)) {
var grp = new SplashGroup(Paths.xml('splashes/$name'));
grpMap.set(name, grp);
}
return grpMap.get(name);
}
public override function destroy() {
super.destroy();
for(grp in grpMap)
grp.destroy();
grpMap = null;
}
public override function destroy() {
super.destroy();
for(grp in grpMap)
grp.destroy();
grpMap = null;
}
var _firstDraw:Bool = true;
public override function draw() {
super.draw();
if (_firstDraw != (_firstDraw = false))
for(grp in grpMap)
grp.draw();
}
var _firstDraw:Bool = true;
public override function draw() {
super.draw();
if (_firstDraw != (_firstDraw = false))
for(grp in grpMap)
grp.draw();
}
var __grp:SplashGroup;
public function showSplash(name:String, strum:Strum) {
__grp = getSplashGroup(name);
add(__grp.showOnStrum(strum));
var __grp:SplashGroup;
public function showSplash(name:String, strum:Strum) {
__grp = getSplashGroup(name);
add(__grp.showOnStrum(strum));
// max 8 rendered splashes
while(members.length > 8)
remove(members[0]);
}
// max 8 rendered splashes
while(members.length > 8)
remove(members[0]);
}
}
+192 -192
View File
@@ -9,227 +9,227 @@ import haxe.io.Path;
using StringTools;
class Stage extends FlxBasic implements IBeatReceiver {
public var stageXML:Access;
public var stagePath:String;
public var stageSprites:Map<String, FlxSprite> = [];
public var stageScript:Script;
public var state:FlxState;
public var characterPoses:Map<String, StageCharPos> = [];
public var stageXML:Access;
public var stagePath:String;
public var stageSprites:Map<String, FlxSprite> = [];
public var stageScript:Script;
public var state:FlxState;
public var characterPoses:Map<String, StageCharPos> = [];
public function getSprite(name:String) {
return stageSprites[name];
}
public function getSprite(name:String) {
return stageSprites[name];
}
public function new(stage:String, ?state:FlxState) {
super();
public function new(stage:String, ?state:FlxState) {
super();
if (state == null) state = PlayState.instance;
if (state == null) state = FlxG.state;
this.state = state;
if (state == null) state = PlayState.instance;
if (state == null) state = FlxG.state;
this.state = state;
stagePath = Paths.xml('stages/$stage');
try {
if (Assets.exists(stagePath)) stageXML = new Access(Xml.parse(Assets.getText(stagePath)).firstElement());
} catch(e) {
Logs.trace('Couldn\'t load stage "$stage": ${e.message}', ERROR);
}
if (stageXML != null) {
stagePath = Paths.xml('stages/$stage');
try {
if (Assets.exists(stagePath)) stageXML = new Access(Xml.parse(Assets.getText(stagePath)).firstElement());
} catch(e) {
Logs.trace('Couldn\'t load stage "$stage": ${e.message}', ERROR);
}
if (stageXML != null) {
var spritesParentFolder = "";
if (PlayState.instance != null) {
if (stageXML.has.zoom) {
var parsed:Null<Float> = Std.parseFloat(stageXML.att.zoom);
if (parsed != null && PlayState.instance != null) PlayState.instance.defaultCamZoom = parsed;
}
PlayState.instance.curStage = stageXML.has.name ? stageXML.att.name : stage;
}
if (stageXML.has.folder) {
spritesParentFolder = stageXML.att.folder;
if (spritesParentFolder.charAt(spritesParentFolder.length-1) != "/") spritesParentFolder = spritesParentFolder + "/";
}
var spritesParentFolder = "";
if (PlayState.instance != null) {
if (stageXML.has.zoom) {
var parsed:Null<Float> = Std.parseFloat(stageXML.att.zoom);
if (parsed != null && PlayState.instance != null) PlayState.instance.defaultCamZoom = parsed;
}
PlayState.instance.curStage = stageXML.has.name ? stageXML.att.name : stage;
}
if (stageXML.has.folder) {
spritesParentFolder = stageXML.att.folder;
if (spritesParentFolder.charAt(spritesParentFolder.length-1) != "/") spritesParentFolder = spritesParentFolder + "/";
}
var elems = [];
for(node in stageXML.elements) {
if (node.name == "high-memory" && !Options.lowMemoryMode)
for(e in node.elements)
elems.push(e);
else
elems.push(node);
}
var elems = [];
for(node in stageXML.elements) {
if (node.name == "high-memory" && !Options.lowMemoryMode)
for(e in node.elements)
elems.push(e);
else
elems.push(node);
}
for(node in elems) {
var sprite:Dynamic = switch(node.name) {
case "sprite" | "spr" | "sparrow":
if (!node.has.sprite || !node.has.name || !node.has.x || !node.has.y) continue;
for(node in elems) {
var sprite:Dynamic = switch(node.name) {
case "sprite" | "spr" | "sparrow":
if (!node.has.sprite || !node.has.name || !node.has.x || !node.has.y) continue;
var spr = XMLUtil.createSpriteFromXML(node, spritesParentFolder, BEAT);
var spr = XMLUtil.createSpriteFromXML(node, spritesParentFolder, BEAT);
if (!node.has.zoomfactor && PlayState.instance != null)
spr.initialZoom = PlayState.instance.defaultCamZoom;
if (!node.has.zoomfactor && PlayState.instance != null)
spr.initialZoom = PlayState.instance.defaultCamZoom;
stageSprites.set(spr.name, spr);
state.add(spr);
spr;
case "box":
if ( !node.has.name || !node.has.width || !node.has.height) continue;
stageSprites.set(spr.name, spr);
state.add(spr);
spr;
case "box":
if ( !node.has.name || !node.has.width || !node.has.height) continue;
var spr = new FlxSprite(
(node.has.x) ? Std.parseFloat(node.att.x) : 0,
(node.has.y) ? Std.parseFloat(node.att.y) : 0
).makeGraphic(
Std.parseInt(node.att.width),
Std.parseInt(node.att.height),
(node.has.color) ? CoolUtil.getColorFromDynamic(node.att.color) : 0xFFFFFFFF
);
var spr = new FlxSprite(
(node.has.x) ? Std.parseFloat(node.att.x) : 0,
(node.has.y) ? Std.parseFloat(node.att.y) : 0
).makeGraphic(
Std.parseInt(node.att.width),
Std.parseInt(node.att.height),
(node.has.color) ? CoolUtil.getColorFromDynamic(node.att.color) : 0xFFFFFFFF
);
stageSprites.set(node.getAtt("name"), spr);
state.add(spr);
spr;
case "boyfriend" | "bf":
addCharPos("boyfriend", node, {
x: 770,
y: 100,
flip: true
});
null;
case "girlfriend" | "gf":
addCharPos("girlfriend", node, {
x: 400,
y: 130,
flip: false
});
null;
case "dad" | "opponent":
addCharPos("dad", node, {
x: 100,
y: 100,
flip: false
});
null;
case "character":
if (!node.has.name) continue;
addCharPos(node.att.name, node);
null;
case "ratings" | "combo":
if (PlayState.instance == null) continue;
PlayState.instance.comboGroup.setPosition(
Std.parseFloat(node.getAtt("x")).getDefault(PlayState.instance.comboGroup.x),
Std.parseFloat(node.getAtt("y")).getDefault(PlayState.instance.comboGroup.y)
);
PlayState.instance.add(PlayState.instance.comboGroup);
PlayState.instance.comboGroup;
default: null;
}
if (sprite != null) {
for(e in node.nodes.property)
XMLUtil.applyXMLProperty(sprite, e);
}
}
}
stageSprites.set(node.getAtt("name"), spr);
state.add(spr);
spr;
case "boyfriend" | "bf":
addCharPos("boyfriend", node, {
x: 770,
y: 100,
flip: true
});
null;
case "girlfriend" | "gf":
addCharPos("girlfriend", node, {
x: 400,
y: 130,
flip: false
});
null;
case "dad" | "opponent":
addCharPos("dad", node, {
x: 100,
y: 100,
flip: false
});
null;
case "character":
if (!node.has.name) continue;
addCharPos(node.att.name, node);
null;
case "ratings" | "combo":
if (PlayState.instance == null) continue;
PlayState.instance.comboGroup.setPosition(
Std.parseFloat(node.getAtt("x")).getDefault(PlayState.instance.comboGroup.x),
Std.parseFloat(node.getAtt("y")).getDefault(PlayState.instance.comboGroup.y)
);
PlayState.instance.add(PlayState.instance.comboGroup);
PlayState.instance.comboGroup;
default: null;
}
if (sprite != null) {
for(e in node.nodes.property)
XMLUtil.applyXMLProperty(sprite, e);
}
}
}
if (characterPoses["girlfriend"] == null)
addCharPos("girlfriend", null, {
x: 400,
y: 130,
flip: false
});
if (characterPoses["girlfriend"] == null)
addCharPos("girlfriend", null, {
x: 400,
y: 130,
flip: false
});
if (characterPoses["dad"] == null)
addCharPos("dad", null, {
x: 100,
y: 100,
flip: false
});
if (characterPoses["dad"] == null)
addCharPos("dad", null, {
x: 100,
y: 100,
flip: false
});
if (characterPoses["boyfriend"] == null)
addCharPos("boyfriend", null, {
x: 770,
y: 100,
flip: true
});
if (characterPoses["boyfriend"] == null)
addCharPos("boyfriend", null, {
x: 770,
y: 100,
flip: true
});
if (PlayState.instance == null) return;
stageScript = Script.create(Paths.script('data/stages/$stage'));
for(k=>e in stageSprites) {
stageScript.set(k, e);
}
PlayState.instance.scripts.add(stageScript);
}
if (PlayState.instance == null) return;
stageScript = Script.create(Paths.script('data/stages/$stage'));
for(k=>e in stageSprites) {
stageScript.set(k, e);
}
PlayState.instance.scripts.add(stageScript);
}
public function addCharPos(name:String, node:Access, ?nonXMLInfo:StageCharPosInfo) {
var dummyBasic:FlxBasic = new FlxBasic();
dummyBasic.active = false;
state.add(dummyBasic);
public function addCharPos(name:String, node:Access, ?nonXMLInfo:StageCharPosInfo) {
var dummyBasic:FlxBasic = new FlxBasic();
dummyBasic.active = false;
state.add(dummyBasic);
characterPoses[name] = {
node: node,
nonXMLInfo: nonXMLInfo,
dummy: dummyBasic
};
characterPoses[name] = {
node: node,
nonXMLInfo: nonXMLInfo,
dummy: dummyBasic
};
}
}
public function isCharFlipped(posName:String, def:Bool = false) {
if (characterPoses[posName] != null) {
var charPos = characterPoses[posName];
if (charPos.node != null && charPos.node.has.flip)
return charPos.node.att.flip == "true";
if (charPos.nonXMLInfo != null)
return characterPoses[posName].nonXMLInfo.flip;
}
return def;
}
public function isCharFlipped(posName:String, def:Bool = false) {
if (characterPoses[posName] != null) {
var charPos = characterPoses[posName];
if (charPos.node != null && charPos.node.has.flip)
return charPos.node.att.flip == "true";
if (charPos.nonXMLInfo != null)
return characterPoses[posName].nonXMLInfo.flip;
}
return def;
}
public function applyCharStuff(char:Character, posName:String) {
if (characterPoses[posName] == null)
state.add(char);
else {
var charPos = characterPoses[posName];
if (charPos.nonXMLInfo != null)
char.setPosition(charPos.nonXMLInfo.x, charPos.nonXMLInfo.y);
if (charPos.node != null)
doCharNodeShit(char, charPos.node);
state.insert(state.members.indexOf(charPos.dummy), char);
}
}
private static function doCharNodeShit(char:Character, node:Access) {
if (node.has.x) {
var x:Null<Float> = Std.parseFloat(node.att.x);
if (x != null) char.x = x;
}
if (node.has.y) {
var y:Null<Float> = Std.parseFloat(node.att.y);
if (y != null) char.y = y;
}
if (node.has.camxoffset) {
var x:Null<Float> = Std.parseFloat(node.att.camxoffset);
if (x != null) char.cameraOffset.x += x;
}
if (node.has.camyoffset) {
var y:Null<Float> = Std.parseFloat(node.att.camyoffset);
if (y != null) char.cameraOffset.y += y;
}
if (node.has.scroll) {
var scroll:Null<Float> = Std.parseFloat(node.att.scroll);
if (scroll != null) char.scrollFactor.set(scroll, scroll);
}
}
public function applyCharStuff(char:Character, posName:String) {
if (characterPoses[posName] == null)
state.add(char);
else {
var charPos = characterPoses[posName];
if (charPos.nonXMLInfo != null)
char.setPosition(charPos.nonXMLInfo.x, charPos.nonXMLInfo.y);
if (charPos.node != null)
doCharNodeShit(char, charPos.node);
state.insert(state.members.indexOf(charPos.dummy), char);
}
}
private static function doCharNodeShit(char:Character, node:Access) {
if (node.has.x) {
var x:Null<Float> = Std.parseFloat(node.att.x);
if (x != null) char.x = x;
}
if (node.has.y) {
var y:Null<Float> = Std.parseFloat(node.att.y);
if (y != null) char.y = y;
}
if (node.has.camxoffset) {
var x:Null<Float> = Std.parseFloat(node.att.camxoffset);
if (x != null) char.cameraOffset.x += x;
}
if (node.has.camyoffset) {
var y:Null<Float> = Std.parseFloat(node.att.camyoffset);
if (y != null) char.cameraOffset.y += y;
}
if (node.has.scroll) {
var scroll:Null<Float> = Std.parseFloat(node.att.scroll);
if (scroll != null) char.scrollFactor.set(scroll, scroll);
}
}
public function beatHit(curBeat:Int) {}
public function beatHit(curBeat:Int) {}
public function stepHit(curStep:Int) {}
public function stepHit(curStep:Int) {}
public function measureHit(curMeasure:Int) {}
}
typedef StageCharPos = {
var node:Access;
var dummy:FlxBasic;
var ?nonXMLInfo:StageCharPosInfo;
var node:Access;
var dummy:FlxBasic;
var ?nonXMLInfo:StageCharPosInfo;
}
typedef StageCharPosInfo = {
var x:Float;
var y:Float;
var flip:Bool;
var x:Float;
var y:Float;
var flip:Bool;
}
+98 -98
View File
@@ -4,122 +4,122 @@ import flixel.math.FlxPoint;
import funkin.system.Conductor;
class Strum extends FlxSprite {
public var cpu = false;
public var lastHit:Float = -5000;
public var cpu = false;
public var lastHit:Float = -5000;
public var scrollSpeed:Null<Float> = null; // custom scroll speed per strum
public var noteAngle:Null<Float> = null; // custom scroll speed per strum
public var scrollSpeed:Null<Float> = null; // custom scroll speed per strum
public var noteAngle:Null<Float> = null; // custom scroll speed per strum
public var lastDrawCameras(default, null):Array<FlxCamera> = [];
public var lastDrawCameras(default, null):Array<FlxCamera> = [];
public inline function getScrollSpeed(?note:Note):Float {
if (note != null && note.scrollSpeed != null) return note.scrollSpeed;
if (scrollSpeed != null) return scrollSpeed;
if (PlayState.instance != null) return PlayState.instance.scrollSpeed;
return 1;
}
public inline function getScrollSpeed(?note:Note):Float {
if (note != null && note.scrollSpeed != null) return note.scrollSpeed;
if (scrollSpeed != null) return scrollSpeed;
if (PlayState.instance != null) return PlayState.instance.scrollSpeed;
return 1;
}
public inline function getNotesAngle(?note:Note):Float {
if (note != null && note.noteAngle != null) return note.noteAngle;
if (noteAngle != null) return noteAngle;
return angle;
}
public inline function getNotesAngle(?note:Note):Float {
if (note != null && note.noteAngle != null) return note.noteAngle;
if (noteAngle != null) return noteAngle;
return angle;
}
public override function update(elapsed:Float) {
super.update(elapsed);
if (cpu) {
if (lastHit + (Conductor.crochet / 2) < Conductor.songPosition && getAnim() == "confirm") {
playAnim("static");
}
}
}
public override function update(elapsed:Float) {
super.update(elapsed);
if (cpu) {
if (lastHit + (Conductor.crochet / 2) < Conductor.songPosition && getAnim() == "confirm") {
playAnim("static");
}
}
}
public override function draw() {
lastDrawCameras = [for(c in cameras) c];
super.draw();
}
public override function draw() {
lastDrawCameras = [for(c in cameras) c];
super.draw();
}
@:noCompletion public static final PIX180:Float = 565.4866776461628; // 180 * Math.PI
@:noCompletion public static final N_WIDTHDIV2:Float = Note.swagWidth / 2;
@:noCompletion public static final PIX180:Float = 565.4866776461628; // 180 * Math.PI
@:noCompletion public static final N_WIDTHDIV2:Float = Note.swagWidth / 2;
public function updateNotePosition(daNote:Note) {
if (!daNote.exists) return;
public function updateNotePosition(daNote:Note) {
if (!daNote.exists) return;
daNote.__strumCameras = lastDrawCameras;
daNote.__strum = this;
daNote.scrollFactor.set(scrollFactor.x, scrollFactor.y);
daNote.__noteAngle = getNotesAngle(daNote);
daNote.angle = daNote.isSustainNote ? daNote.__noteAngle : angle;
daNote.__strumCameras = lastDrawCameras;
daNote.__strum = this;
daNote.scrollFactor.set(scrollFactor.x, scrollFactor.y);
daNote.__noteAngle = getNotesAngle(daNote);
daNote.angle = daNote.isSustainNote ? daNote.__noteAngle : angle;
if (daNote.strumRelativePos) {
daNote.setPosition(daNote.isSustainNote ? ((Note.swagWidth - daNote.width) / 2) : 0, (daNote.strumTime - Conductor.songPosition) * (0.45 * FlxMath.roundDecimal(getScrollSpeed(daNote), 2)));
if (daNote.isSustainNote) daNote.y += N_WIDTHDIV2;
} else {
var offset = FlxPoint.get(0, (Conductor.songPosition - daNote.strumTime) * (0.45 * FlxMath.roundDecimal(getScrollSpeed(daNote), 2)));
var realOffset = FlxPoint.get(0, 0);
if (daNote.strumRelativePos) {
daNote.setPosition(daNote.isSustainNote ? ((Note.swagWidth - daNote.width) / 2) : 0, (daNote.strumTime - Conductor.songPosition) * (0.45 * FlxMath.roundDecimal(getScrollSpeed(daNote), 2)));
if (daNote.isSustainNote) daNote.y += N_WIDTHDIV2;
} else {
var offset = FlxPoint.get(0, (Conductor.songPosition - daNote.strumTime) * (0.45 * FlxMath.roundDecimal(getScrollSpeed(daNote), 2)));
var realOffset = FlxPoint.get(0, 0);
if (daNote.isSustainNote) offset.y -= N_WIDTHDIV2;
if (daNote.isSustainNote) offset.y -= N_WIDTHDIV2;
if (Std.int(daNote.__noteAngle % 360) != 0) {
var noteAngleCos = FlxMath.fastCos(daNote.__noteAngle / PIX180);
var noteAngleSin = FlxMath.fastSin(daNote.__noteAngle / PIX180);
if (Std.int(daNote.__noteAngle % 360) != 0) {
var noteAngleCos = FlxMath.fastCos(daNote.__noteAngle / PIX180);
var noteAngleSin = FlxMath.fastSin(daNote.__noteAngle / PIX180);
var aOffset:FlxPoint = FlxPoint.get(
(daNote.origin.x / daNote.scale.x) - daNote.offset.x,
(daNote.origin.y / daNote.scale.y) - daNote.offset.y
);
realOffset.x = -aOffset.x + (noteAngleCos * (offset.x + aOffset.x)) + (noteAngleSin * (offset.y + aOffset.y));
realOffset.y = -aOffset.y + (noteAngleSin * (offset.x + aOffset.x)) + (noteAngleCos * (offset.y + aOffset.y));
var aOffset:FlxPoint = FlxPoint.get(
(daNote.origin.x / daNote.scale.x) - daNote.offset.x,
(daNote.origin.y / daNote.scale.y) - daNote.offset.y
);
realOffset.x = -aOffset.x + (noteAngleCos * (offset.x + aOffset.x)) + (noteAngleSin * (offset.y + aOffset.y));
realOffset.y = -aOffset.y + (noteAngleSin * (offset.x + aOffset.x)) + (noteAngleCos * (offset.y + aOffset.y));
aOffset.put();
} else {
realOffset.x = offset.x;
realOffset.y = offset.y;
}
realOffset.y *= -1;
aOffset.put();
} else {
realOffset.x = offset.x;
realOffset.y = offset.y;
}
realOffset.y *= -1;
daNote.setPosition(x + realOffset.x, y + realOffset.y);
daNote.setPosition(x + realOffset.x, y + realOffset.y);
offset.put();
realOffset.put();
}
}
offset.put();
realOffset.put();
}
}
public function updateSustain(daNote:Note) {
if (!daNote.isSustainNote) return;
daNote.updateSustain(this);
}
public function updateSustain(daNote:Note) {
if (!daNote.isSustainNote) return;
daNote.updateSustain(this);
}
public function updatePlayerInput(pressed:Bool, justPressed:Bool, justReleased:Bool) {
switch(getAnim()) {
case "confirm":
if (justReleased || !pressed)
playAnim("static");
case "pressed":
if (justReleased || !pressed)
playAnim("static");
case "static":
if (justPressed || pressed)
playAnim("pressed");
case null:
playAnim("static");
}
centerOffsets();
centerOrigin();
}
public function updatePlayerInput(pressed:Bool, justPressed:Bool, justReleased:Bool) {
switch(getAnim()) {
case "confirm":
if (justReleased || !pressed)
playAnim("static");
case "pressed":
if (justReleased || !pressed)
playAnim("static");
case "static":
if (justPressed || pressed)
playAnim("pressed");
case null:
playAnim("static");
}
centerOffsets();
centerOrigin();
}
public function press(time:Float) {
lastHit = time;
playAnim("confirm");
}
public function press(time:Float) {
lastHit = time;
playAnim("confirm");
}
public function playAnim(anim:String, force:Bool = true) {
var oldAnim = animation.curAnim;
animation.play(anim, force);
centerOffsets();
centerOrigin();
}
public function getAnim() {
return animation.curAnim == null ? null : animation.curAnim.name;
}
public function playAnim(anim:String, force:Bool = true) {
var oldAnim = animation.curAnim;
animation.play(anim, force);
centerOffsets();
centerOrigin();
}
public function getAnim() {
return animation.curAnim == null ? null : animation.curAnim.name;
}
}
+177 -177
View File
@@ -9,206 +9,206 @@ import funkin.system.Controls;
import flixel.tweens.FlxTween;
class StrumLine extends FlxTypedGroup<Strum> {
/**
* Signal that triggers whenever a note is hit. Similar to onPlayerHit and onDadHit, except strumline specific.
* To add a listener, do
* `strumLine.onHit.add(function(e:NoteHitEvent) {});`
*/
public var onHit:FlxTypedSignal<NoteHitEvent->Void> = new FlxTypedSignal<NoteHitEvent->Void>();
/**
* Signal that triggers whenever a note is missed. Similar to onPlayerMiss and onDadMiss, except strumline specific.
* To add a listener, do
* `strumLine.onMiss.add(function(e:NoteHitEvent) {});`
*/
public var onMiss:FlxTypedSignal<NoteHitEvent->Void> = new FlxTypedSignal<NoteHitEvent->Void>();
/**
* Signal that triggers whenever a note is being updated. Similar to onNoteUpdate, except strumline specific.
* To add a listener, do
* `strumLine.onNoteUpdate.add(function(e:NoteUpdateEvent) {});`
*/
public var onNoteUpdate:FlxTypedSignal<NoteUpdateEvent->Void> = new FlxTypedSignal<NoteUpdateEvent->Void>();
/**
* Array containing all of the characters "attached" to those strums.
*/
public var characters:Array<Character>;
/**
* Whenever this strumline is controlled by cpu or not.
*/
public var cpu(default, set):Bool = false;
/**
* Whenever this strumline is from the opponent side or the player side.
*/
public var opponentSide:Bool = false;
/**
* Controls assigned to this strumline.
*/
public var controls:Controls = null;
/**
* Chart JSON data assigned to this StrumLine (Codename format)
*/
public var data:ChartStrumLine = null;
/**
* Whenever Ghost Tapping is enabled.
*/
@:isVar public var ghostTapping(get, set):Null<Bool> = null;
/**
* Signal that triggers whenever a note is hit. Similar to onPlayerHit and onDadHit, except strumline specific.
* To add a listener, do
* `strumLine.onHit.add(function(e:NoteHitEvent) {});`
*/
public var onHit:FlxTypedSignal<NoteHitEvent->Void> = new FlxTypedSignal<NoteHitEvent->Void>();
/**
* Signal that triggers whenever a note is missed. Similar to onPlayerMiss and onDadMiss, except strumline specific.
* To add a listener, do
* `strumLine.onMiss.add(function(e:NoteHitEvent) {});`
*/
public var onMiss:FlxTypedSignal<NoteHitEvent->Void> = new FlxTypedSignal<NoteHitEvent->Void>();
/**
* Signal that triggers whenever a note is being updated. Similar to onNoteUpdate, except strumline specific.
* To add a listener, do
* `strumLine.onNoteUpdate.add(function(e:NoteUpdateEvent) {});`
*/
public var onNoteUpdate:FlxTypedSignal<NoteUpdateEvent->Void> = new FlxTypedSignal<NoteUpdateEvent->Void>();
/**
* Array containing all of the characters "attached" to those strums.
*/
public var characters:Array<Character>;
/**
* Whenever this strumline is controlled by cpu or not.
*/
public var cpu(default, set):Bool = false;
/**
* Whenever this strumline is from the opponent side or the player side.
*/
public var opponentSide:Bool = false;
/**
* Controls assigned to this strumline.
*/
public var controls:Controls = null;
/**
* Chart JSON data assigned to this StrumLine (Codename format)
*/
public var data:ChartStrumLine = null;
/**
* Whenever Ghost Tapping is enabled.
*/
@:isVar public var ghostTapping(get, set):Null<Bool> = null;
/**
* Group of all of the notes in this strumline. Using `forEach` on this group will only loop through the first notes for performance reasons.
*/
public var notes:NoteGroup;
private function get_ghostTapping() {
if (this.ghostTapping != null) return this.ghostTapping;
if (PlayState.instance != null) return PlayState.instance.ghostTapping;
return false;
}
private function get_ghostTapping() {
if (this.ghostTapping != null) return this.ghostTapping;
if (PlayState.instance != null) return PlayState.instance.ghostTapping;
return false;
}
private inline function set_ghostTapping(b:Bool):Bool
return this.ghostTapping = b;
private inline function set_ghostTapping(b:Bool):Bool
return this.ghostTapping = b;
private var strumOffset:Float = 0.25;
private var strumOffset:Float = 0.25;
public function new(characters:Array<Character>, strumOffset:Float = 0.25, cpu:Bool = false, opponentSide:Bool = true, ?controls:Controls) {
super();
this.characters = characters;
this.strumOffset = strumOffset;
this.cpu = cpu;
this.opponentSide = opponentSide;
this.controls = controls;
this.notes = new NoteGroup();
}
public function new(characters:Array<Character>, strumOffset:Float = 0.25, cpu:Bool = false, opponentSide:Bool = true, ?controls:Controls) {
super();
this.characters = characters;
this.strumOffset = strumOffset;
this.cpu = cpu;
this.opponentSide = opponentSide;
this.controls = controls;
this.notes = new NoteGroup();
}
public function generate(strumLine:ChartStrumLine) {
if (strumLine.notes != null) for(note in strumLine.notes) {
notes.add(new Note(this, note, false));
public function generate(strumLine:ChartStrumLine) {
if (strumLine.notes != null) for(note in strumLine.notes) {
notes.add(new Note(this, note, false));
if (note.sLen > Conductor.stepCrochet * 0.75) {
var len:Float = note.sLen;
var curLen:Float = 0;
while(len > 10) {
curLen = Math.min(len, Conductor.stepCrochet);
notes.add(new Note(this, note, true, curLen, note.sLen - len));
len -= curLen;
}
}
}
notes.sortNotes();
}
if (note.sLen > Conductor.stepCrochet * 0.75) {
var len:Float = note.sLen;
var curLen:Float = 0;
while(len > 10) {
curLen = Math.min(len, Conductor.stepCrochet);
notes.add(new Note(this, note, true, curLen, note.sLen - len));
len -= curLen;
}
}
}
notes.sortNotes();
}
public override function update(elapsed:Float) {
super.update(elapsed);
notes.update(elapsed);
}
public override function update(elapsed:Float) {
super.update(elapsed);
notes.update(elapsed);
}
public override function draw() {
super.draw();
notes.cameras = cameras;
notes.draw();
}
public override function draw() {
super.draw();
notes.cameras = cameras;
notes.draw();
}
public function updateNotes() {
notes.forEach(updateNote);
}
public function updateNotes() {
notes.forEach(updateNote);
}
var __updateNote_strum:Strum;
public function updateNote(daNote:Note) {
var __updateNote_strum:Strum;
public function updateNote(daNote:Note) {
for(e in members) {
if (e.ID == daNote.noteData % 4) {
__updateNote_strum = e;
break; //ing bad
}
}
PlayState.instance.scripts.event("onNoteUpdate", PlayState.instance.__updateNote_event.recycle(daNote, FlxG.elapsed, __updateNote_strum));
onNoteUpdate.dispatch(PlayState.instance.__updateNote_event);
if (PlayState.instance.__updateNote_event.cancelled) return;
for(e in members) {
if (e.ID == daNote.noteData % 4) {
__updateNote_strum = e;
break; //ing bad
}
}
PlayState.instance.scripts.event("onNoteUpdate", PlayState.instance.__updateNote_event.recycle(daNote, FlxG.elapsed, __updateNote_strum));
onNoteUpdate.dispatch(PlayState.instance.__updateNote_event);
if (PlayState.instance.__updateNote_event.cancelled) return;
if (PlayState.instance.__updateNote_event.__updateHitWindow) {
daNote.canBeHit = (daNote.strumTime > Conductor.songPosition - (PlayState.instance.hitWindow * daNote.latePressWindow)
&& daNote.strumTime < Conductor.songPosition + (PlayState.instance.hitWindow * daNote.earlyPressWindow));
if (PlayState.instance.__updateNote_event.__updateHitWindow) {
daNote.canBeHit = (daNote.strumTime > Conductor.songPosition - (PlayState.instance.hitWindow * daNote.latePressWindow)
&& daNote.strumTime < Conductor.songPosition + (PlayState.instance.hitWindow * daNote.earlyPressWindow));
if (daNote.strumTime < Conductor.songPosition - PlayState.instance.hitWindow && !daNote.wasGoodHit)
daNote.tooLate = true;
}
if (daNote.strumTime < Conductor.songPosition - PlayState.instance.hitWindow && !daNote.wasGoodHit)
daNote.tooLate = true;
}
if (PlayState.instance.__updateNote_event.__autoCPUHit && cpu && !daNote.wasGoodHit && daNote.strumTime < Conductor.songPosition) PlayState.instance.goodNoteHit(this, daNote);
if (PlayState.instance.__updateNote_event.__autoCPUHit && cpu && !daNote.wasGoodHit && daNote.strumTime < Conductor.songPosition) PlayState.instance.goodNoteHit(this, daNote);
if (daNote.wasGoodHit && daNote.isSustainNote && daNote.strumTime + (daNote.sustainLength) < Conductor.songPosition) {
deleteNote(daNote);
return;
}
if (daNote.wasGoodHit && daNote.isSustainNote && daNote.strumTime + (daNote.sustainLength) < Conductor.songPosition) {
deleteNote(daNote);
return;
}
if (daNote.tooLate && !cpu) {
PlayState.instance.noteMiss(this, daNote);
return;
}
if (daNote.tooLate && !cpu) {
PlayState.instance.noteMiss(this, daNote);
return;
}
if (PlayState.instance.__updateNote_event.strum == null) return;
if (PlayState.instance.__updateNote_event.strum == null) return;
if (PlayState.instance.__updateNote_event.__reposNote) PlayState.instance.__updateNote_event.strum.updateNotePosition(daNote);
PlayState.instance.__updateNote_event.strum.updateSustain(daNote);
if (PlayState.instance.__updateNote_event.__reposNote) PlayState.instance.__updateNote_event.strum.updateNotePosition(daNote);
PlayState.instance.__updateNote_event.strum.updateSustain(daNote);
PlayState.instance.scripts.event("onNotePostUpdate", PlayState.instance.__updateNote_event);
}
PlayState.instance.scripts.event("onNotePostUpdate", PlayState.instance.__updateNote_event);
}
public inline function addHealth(health:Float)
PlayState.instance.health += health * (opponentSide ? -1 : 1);
public inline function addHealth(health:Float)
PlayState.instance.health += health * (opponentSide ? -1 : 1);
public function generateStrums(amount:Int = 4) {
for (i in 0...4)
{
var babyArrow:Strum = new Strum((FlxG.width * strumOffset) + (Note.swagWidth * (i - 2)), PlayState.instance.strumLine.y);
babyArrow.ID = i;
public function generateStrums(amount:Int = 4) {
for (i in 0...4)
{
var babyArrow:Strum = new Strum((FlxG.width * strumOffset) + (Note.swagWidth * (i - 2)), PlayState.instance.strumLine.y);
babyArrow.ID = i;
var event = PlayState.instance.scripts.event("onStrumCreation", EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.indexOf(this), i));
var event = PlayState.instance.scripts.event("onStrumCreation", EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.indexOf(this), i));
if (!event.cancelled) {
babyArrow.frames = Paths.getFrames(event.sprite);
babyArrow.animation.addByPrefix('green', 'arrowUP');
babyArrow.animation.addByPrefix('blue', 'arrowDOWN');
babyArrow.animation.addByPrefix('purple', 'arrowLEFT');
babyArrow.animation.addByPrefix('red', 'arrowRIGHT');
if (!event.cancelled) {
babyArrow.frames = Paths.getFrames(event.sprite);
babyArrow.animation.addByPrefix('green', 'arrowUP');
babyArrow.animation.addByPrefix('blue', 'arrowDOWN');
babyArrow.animation.addByPrefix('purple', 'arrowLEFT');
babyArrow.animation.addByPrefix('red', 'arrowRIGHT');
babyArrow.antialiasing = true;
babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7));
babyArrow.antialiasing = true;
babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7));
switch (babyArrow.ID % 4)
{
case 0:
babyArrow.animation.addByPrefix('static', 'arrowLEFT');
babyArrow.animation.addByPrefix('pressed', 'left press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'left confirm', 24, false);
case 1:
babyArrow.animation.addByPrefix('static', 'arrowDOWN');
babyArrow.animation.addByPrefix('pressed', 'down press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'down confirm', 24, false);
case 2:
babyArrow.animation.addByPrefix('static', 'arrowUP');
babyArrow.animation.addByPrefix('pressed', 'up press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'up confirm', 24, false);
case 3:
babyArrow.animation.addByPrefix('static', 'arrowRIGHT');
babyArrow.animation.addByPrefix('pressed', 'right press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false);
}
}
switch (babyArrow.ID % 4)
{
case 0:
babyArrow.animation.addByPrefix('static', 'arrowLEFT');
babyArrow.animation.addByPrefix('pressed', 'left press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'left confirm', 24, false);
case 1:
babyArrow.animation.addByPrefix('static', 'arrowDOWN');
babyArrow.animation.addByPrefix('pressed', 'down press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'down confirm', 24, false);
case 2:
babyArrow.animation.addByPrefix('static', 'arrowUP');
babyArrow.animation.addByPrefix('pressed', 'up press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'up confirm', 24, false);
case 3:
babyArrow.animation.addByPrefix('static', 'arrowRIGHT');
babyArrow.animation.addByPrefix('pressed', 'right press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false);
}
}
babyArrow.cpu = cpu;
babyArrow.updateHitbox();
babyArrow.scrollFactor.set();
babyArrow.cpu = cpu;
babyArrow.updateHitbox();
babyArrow.scrollFactor.set();
if (event.__doAnimation)
{
babyArrow.y -= 10;
babyArrow.alpha = 0;
FlxTween.tween(babyArrow, {y: babyArrow.y + 10, alpha: 1}, 1, {ease: FlxEase.circOut, startDelay: 0.5 + (0.2 * i)});
}
if (event.__doAnimation)
{
babyArrow.y -= 10;
babyArrow.alpha = 0;
FlxTween.tween(babyArrow, {y: babyArrow.y + 10, alpha: 1}, 1, {ease: FlxEase.circOut, startDelay: 0.5 + (0.2 * i)});
}
add(babyArrow);
add(babyArrow);
babyArrow.playAnim('static');
}
}
babyArrow.playAnim('static');
}
}
/**
* Deletes a note from this strumline.
@@ -224,15 +224,15 @@ class StrumLine extends FlxTypedGroup<Strum> {
}
}
/**
* SETTERS & GETTERS
*/
#if REGION
private inline function set_cpu(b:Bool):Bool {
for(s in members)
if (s != null)
s.cpu = b;
return cpu = b;
}
#end
/**
* SETTERS & GETTERS
*/
#if REGION
private inline function set_cpu(b:Bool):Bool {
for(s in members)
if (s != null)
s.cpu = b;
return cpu = b;
}
#end
}
+86 -86
View File
@@ -7,57 +7,57 @@ import haxe.Http;
// TODO: Document further and perhaps make this a Haxelib.
class GitHub {
/**
* Gets all the releases from a specific GitHub repository using the GitHub API.
* @param user
* @param repository
* @return Releases
*/
public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array<GitHubRelease> {
try {
var url = 'https://api.github.com/repos/${user}/${repository}/releases';
/**
* Gets all the releases from a specific GitHub repository using the GitHub API.
* @param user
* @param repository
* @return Releases
*/
public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array<GitHubRelease> {
try {
var url = 'https://api.github.com/repos/${user}/${repository}/releases';
var data = Json.parse(__requestOnGitHubServers(url));
if (!(data is Array))
throw __parseGitHubException(data);
var data = Json.parse(__requestOnGitHubServers(url));
if (!(data is Array))
throw __parseGitHubException(data);
return data;
} catch(e) {
if (onError != null)
onError(e);
}
return [];
}
return data;
} catch(e) {
if (onError != null)
onError(e);
}
return [];
}
public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array<GitHubContributor> {
try {
var url = 'https://api.github.com/repos/${user}/${repository}/contributors';
public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array<GitHubContributor> {
try {
var url = 'https://api.github.com/repos/${user}/${repository}/contributors';
var data = Json.parse(__requestOnGitHubServers(url));
if (!(data is Array))
throw __parseGitHubException(data);
var data = Json.parse(__requestOnGitHubServers(url));
if (!(data is Array))
throw __parseGitHubException(data);
return data;
} catch(e) {
if (onError != null)
onError(e);
}
return [];
}
return data;
} catch(e) {
if (onError != null)
onError(e);
}
return [];
}
/**
* Filters all releases gotten by `getReleases`
* @param releases Releases
* @param keepPrereleases Whenever to keep Pre-Releases.
* @param keepDrafts Whenever to keep Drafts.
* @return Filtered releases.
*/
public static inline function filterReleases(releases:Array<GitHubRelease>, keepPrereleases:Bool = true, keepDrafts:Bool = false)
return [for(release in releases) if (release != null && (!release.prerelease || (release.prerelease && keepPrereleases)) && (!release.draft || (release.draft && keepDrafts))) release];
/**
* Filters all releases gotten by `getReleases`
* @param releases Releases
* @param keepPrereleases Whenever to keep Pre-Releases.
* @param keepDrafts Whenever to keep Drafts.
* @return Filtered releases.
*/
public static inline function filterReleases(releases:Array<GitHubRelease>, keepPrereleases:Bool = true, keepDrafts:Bool = false)
return [for(release in releases) if (release != null && (!release.prerelease || (release.prerelease && keepPrereleases)) && (!release.draft || (release.draft && keepDrafts))) release];
public static function __requestOnGitHubServers(url:String) {
var h = new Http(url);
h.setHeader("User-Agent", "request");
public static function __requestOnGitHubServers(url:String) {
var h = new Http(url);
h.setHeader("User-Agent", "request");
var r = null;
h.onData = function(d) {
r = d;
@@ -67,10 +67,10 @@ class GitHub {
}
h.request(false);
return r;
}
public static function __requestBytesOnGitHubServers(url:String) {
var h = new Http(url);
h.setHeader("User-Agent", "request");
}
public static function __requestBytesOnGitHubServers(url:String) {
var h = new Http(url);
h.setHeader("User-Agent", "request");
var r = null;
h.onBytes = function(d) {
r = d;
@@ -80,16 +80,16 @@ class GitHub {
}
h.request(false);
return r;
}
private static function __parseGitHubException(obj:Dynamic):GitHubException {
var msg:String = "(No message)";
var url:String = "(No API url)";
if (Reflect.hasField(obj, "message"))
msg = Reflect.field(obj, "message");
if (Reflect.hasField(obj, "documentation_url"))
url = Reflect.field(obj, "documentation_url");
return new GitHubException(msg, url);
}
}
private static function __parseGitHubException(obj:Dynamic):GitHubException {
var msg:String = "(No message)";
var url:String = "(No API url)";
if (Reflect.hasField(obj, "message"))
msg = Reflect.field(obj, "message");
if (Reflect.hasField(obj, "documentation_url"))
url = Reflect.field(obj, "documentation_url");
return new GitHubException(msg, url);
}
}
#else
@@ -97,38 +97,38 @@ import haxe.Json;
import haxe.Exception;
class GitHub {
/**
* Gets all the releases from a specific GitHub repository using the GitHub API.
* @param user
* @param repository
* @return Releases
*/
public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array<GitHubRelease> {
return [];
}
/**
* Gets all the releases from a specific GitHub repository using the GitHub API.
* @param user
* @param repository
* @return Releases
*/
public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array<GitHubRelease> {
return [];
}
public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array<GitHubContributor> {
return [];
}
public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array<GitHubContributor> {
return [];
}
/**
* Filters all releases gotten by `getReleases`
* @param releases Releases
* @param keepPrereleases Whenever to keep Pre-Releases.
* @param keepDrafts Whenever to keep Drafts.
* @return Filtered releases.
*/
public static inline function filterReleases(releases:Array<GitHubRelease>, keepPrereleases:Bool = true, keepDrafts:Bool = false)
return releases;
/**
* Filters all releases gotten by `getReleases`
* @param releases Releases
* @param keepPrereleases Whenever to keep Pre-Releases.
* @param keepDrafts Whenever to keep Drafts.
* @return Filtered releases.
*/
public static inline function filterReleases(releases:Array<GitHubRelease>, keepPrereleases:Bool = true, keepDrafts:Bool = false)
return releases;
public static function __requestOnGitHubServers(url:String) {
public static function __requestOnGitHubServers(url:String) {
return null;
}
public static function __requestBytesOnGitHubServers(url:String) {
}
public static function __requestBytesOnGitHubServers(url:String) {
return null;
}
private static function __parseGitHubException(obj:Dynamic):GitHubException {
return null;
}
}
private static function __parseGitHubException(obj:Dynamic):GitHubException {
return null;
}
}
#end
+13 -13
View File
@@ -3,17 +3,17 @@ package funkin.github;
import funkin.github.GitHubUser;
typedef GitHubAsset = {
var url:String;
var id:Int;
var node_id:String;
var name:String;
var label:String;
var uploader:GitHubUser;
var content_type:String;
var state:String;
var size:UInt;
var download_count:Int;
var created_at:String;
var updated_at:String;
var browser_download_url:String;
var url:String;
var id:Int;
var node_id:String;
var name:String;
var label:String;
var uploader:GitHubUser;
var content_type:String;
var state:String;
var size:UInt;
var download_count:Int;
var created_at:String;
var updated_at:String;
var browser_download_url:String;
}
+19 -19
View File
@@ -1,23 +1,23 @@
package funkin.github;
typedef GitHubContributor = {
var login:String;
var id:Int;
var node_id:String;
var avatar_url:String;
var gravatar_id:String;
var url:String;
var html_url:String;
var followers_url:String;
var following_url:String;
var gists_url:String;
var starred_url:String;
var subscriptions_url:String;
var organizations_url:String;
var repos_url:String;
var events_url:String;
var received_events_url:String;
var type:String;
var site_admin:Bool;
var contributions:Int;
var login:String;
var id:Int;
var node_id:String;
var avatar_url:String;
var gravatar_id:String;
var url:String;
var html_url:String;
var followers_url:String;
var following_url:String;
var gists_url:String;
var starred_url:String;
var subscriptions_url:String;
var organizations_url:String;
var repos_url:String;
var events_url:String;
var received_events_url:String;
var type:String;
var site_admin:Bool;
var contributions:Int;
}
+7 -7
View File
@@ -3,13 +3,13 @@ package funkin.github;
import haxe.Exception;
class GitHubException extends Exception {
public var apiMessage:String;
public var apiMessage:String;
public var documentationUrl:String;
public var documentationUrl:String;
public function new(apiMessage:String, documentationUrl:String) {
super('[GitHubException] ${apiMessage} (Check ${documentationUrl})');
this.apiMessage = apiMessage;
this.documentationUrl = documentationUrl;
}
public function new(apiMessage:String, documentationUrl:String) {
super('[GitHubException] ${apiMessage} (Check ${documentationUrl})');
this.apiMessage = apiMessage;
this.documentationUrl = documentationUrl;
}
}
+9 -9
View File
@@ -1,13 +1,13 @@
package funkin.github;
typedef GitHubReactions = {
var url:String;
var total_count:Int;
// +1 and -1 cant be added, you need to use Reflect.field
var laugh:Int;
var hooray:Int;
var confused:Int;
var heart:Int;
var rocket:Int;
var eyes:Int;
var url:String;
var total_count:Int;
// +1 and -1 cant be added, you need to use Reflect.field
var laugh:Int;
var hooray:Int;
var confused:Int;
var heart:Int;
var rocket:Int;
var eyes:Int;
}
+40 -40
View File
@@ -1,62 +1,62 @@
package funkin.github;
typedef GitHubRelease = {
/**
* Body of the GitHub request (Markdown)
*/
var body:String;
/**
* Body of the GitHub request (Markdown)
*/
var body:String;
/**
* Url of the release (GitHub API)
*/
var url:String;
/**
* Url of the release (GitHub API)
*/
var url:String;
/**
* Url for the assets JSON. Also accessible via `GitHubRelease.assets`
*/
var assets_url:String;
/**
* Url for the assets JSON. Also accessible via `GitHubRelease.assets`
*/
var assets_url:String;
/**
* Template URL for asset download link.
*/
var upload_url:String;
/**
* Template URL for asset download link.
*/
var upload_url:String;
/**
* Link to the release on the GitHub website.
*/
var html_url:String;
/**
* Link to the release on the GitHub website.
*/
var html_url:String;
/**
* ID of the release.
*/
var id:Int;
/**
* ID of the release.
*/
var id:Int;
/**
* Author of the release
*/
var author:GitHubUser;
/**
* Author of the release
*/
var author:GitHubUser;
var node_id:String;
var node_id:String;
var tag_name:String;
var tag_name:String;
var target_commitish:String;
var target_commitish:String;
var name:String;
var name:String;
var draft:Bool;
var draft:Bool;
var prerelease:Bool;
var prerelease:Bool;
var created_at:String;
var created_at:String;
var published_at:String;
var published_at:String;
var assets:Array<GitHubAsset>;
var assets:Array<GitHubAsset>;
var tarball_url:String;
var tarball_url:String;
var zipball_url:String;
var zipball_url:String;
var reactions:GitHubReactions;
var reactions:GitHubReactions;
}
+96 -96
View File
@@ -2,131 +2,131 @@ package funkin.github;
typedef GitHubUser = {
/**
* Username of the user.
*/
var login:String;
/**
* Username of the user.
*/
var login:String;
/**
* ID of the user.
*/
var id:Int;
/**
* ID of the user.
*/
var id:Int;
/**
* ID of the current node on the GitHub database.
*/
var node_id:String;
/**
* ID of the current node on the GitHub database.
*/
var node_id:String;
/**
* Link to the avatar (profile picture).
*/
var avatar_url:String;
/**
* Link to the avatar (profile picture).
*/
var avatar_url:String;
/**
* Unknown
*/
var gravatar_id:String;
/**
* Unknown
*/
var gravatar_id:String;
/**
* URL to the user on GitHub's servers.
*/
var url:String;
/**
* URL to the user on GitHub's servers.
*/
var url:String;
/**
* URL to the user on GitHub's website.
*/
var html_url:String;
/**
* URL to the user on GitHub's website.
*/
var html_url:String;
/**
* URL on GitHub's API to access this user's followers.
*/
var followers_url:String;
/**
* URL on GitHub's API to access this user's followers.
*/
var followers_url:String;
/**
* URL on GitHub's API to access the accounts this user is following.
*/
var following_url:String;
/**
* URL on GitHub's API to access the accounts this user is following.
*/
var following_url:String;
/**
* URL on GitHub's API to access this user's gists.
*/
var gists_url:String;
/**
* URL on GitHub's API to access this user's gists.
*/
var gists_url:String;
/**
* URL on GitHub's API to access this user's starred repositories.
*/
var starred_url:String;
/**
* URL on GitHub's API to access this user's starred repositories.
*/
var starred_url:String;
// NOT COMPLETE: MISSING repos_url, organizations_url, subscriptions_url, events_url, received_events_url.
// NOT COMPLETE: MISSING repos_url, organizations_url, subscriptions_url, events_url, received_events_url.
/**
* Type of the user.
*/
var type:GitHubUserType;
/**
* Type of the user.
*/
var type:GitHubUserType;
/**
* Whenever the user is a GitHub administrator.
*/
var site_admin:Bool;
/**
* Whenever the user is a GitHub administrator.
*/
var site_admin:Bool;
/**
* Name of the user.
*/
var name:String;
/**
* Name of the user.
*/
var name:String;
/**
* The company this user belongs to. Can be `null`.
*/
var company:String;
/**
* The company this user belongs to. Can be `null`.
*/
var company:String;
var blog:String;
var blog:String;
var location:String;
var location:String;
var email:String;
var email:String;
var hireable:Null<Bool>;
var hireable:Null<Bool>;
var bio:String;
var bio:String;
/**
* Twitter username of the user. Can be null.
*/
var twitter_username:String;
/**
* Twitter username of the user. Can be null.
*/
var twitter_username:String;
/**
* Number of public repos this user own.
*/
var public_repos:Int;
/**
* Number of public repos this user own.
*/
var public_repos:Int;
/**
* Number of public gists this user own.
*/
var public_gists:Int;
/**
* Number of public gists this user own.
*/
var public_gists:Int;
/**
* Number of followers this user have
*/
var followers:Int;
/**
* Number of followers this user have
*/
var followers:Int;
/**
* Number of accounts this user follows.
*/
var following:Int;
/**
* Number of accounts this user follows.
*/
var following:Int;
/**
* Date of creation of the account
*/
var created_at:String;
/**
* Date of creation of the account
*/
var created_at:String;
/**
* Date of last account update.
*/
var updated_at:String;
/**
* Date of last account update.
*/
var updated_at:String;
}
@:enum
abstract GitHubUserType(String) {
var USER = "User";
var ORGANIZATION = "Organization";
var USER = "User";
var ORGANIZATION = "Organization";
}
+3 -3
View File
@@ -1,7 +1,7 @@
package funkin.interfaces;
interface IBeatReceiver {
public function measureHit(curMeasure:Int):Void;
public function beatHit(curBeat:Int):Void;
public function stepHit(curStep:Int):Void;
public function measureHit(curMeasure:Int):Void;
public function beatHit(curBeat:Int):Void;
public function stepHit(curStep:Int):Void;
}
@@ -1,5 +1,5 @@
package funkin.interfaces;
interface IOffsetCompatible {
public function addOffset(anim:String, x:Float = 0, y:Float = 0):Void;
public function addOffset(anim:String, x:Float = 0, y:Float = 0):Void;
}
+92 -92
View File
@@ -6,113 +6,113 @@ package funkin.macros;
* It adds the `recycle` function, which allows you to "reset" an event's values.
*/
class EventMacro {
public static function build():Array<Field> {
var fields = Context.getBuildFields();
public static function build():Array<Field> {
var fields = Context.getBuildFields();
var curClassRest = Context.getLocalClass();
if (curClassRest == null) return fields;
var curClassRest = Context.getLocalClass();
if (curClassRest == null) return fields;
var curClass = curClassRest.get();
if (curClass == null || curClass.name == "CancellableEvent") return fields;
var curClass = curClassRest.get();
if (curClass == null || curClass.name == "CancellableEvent") return fields;
// gets all fields
var values:Array<EventVar> = [];
var hiddenValues:Array<EventVar> = [];
for(field in fields) {
if (field.access.contains(AStatic)) continue;
// gets all fields
var values:Array<EventVar> = [];
var hiddenValues:Array<EventVar> = [];
for(field in fields) {
if (field.access.contains(AStatic)) continue;
var hidden = false;
if (field.meta != null)
for(m in field.meta)
if (m.name == ":dox")
hidden = true;
if (!field.access.contains(APublic)) hidden = true;
var hidden = false;
if (field.meta != null)
for(m in field.meta)
if (m.name == ":dox")
hidden = true;
if (!field.access.contains(APublic)) hidden = true;
switch(field.kind) {
case FVar(type, expr):
(hidden ? hiddenValues : values).push({
name: field.name,
type: type,
expr: expr
});
default:
continue;
}
}
switch(field.kind) {
case FVar(type, expr):
(hidden ? hiddenValues : values).push({
name: field.name,
type: type,
expr: expr
});
default:
continue;
}
}
// add recycle option
var func:Function = {
args: [for(a in values) {
value: a.expr,
type: a.type,
opt: false,
name: a.name
}],
expr: {
pos: Context.currentPos(),
expr: EBlock([])
}
};
// add recycle option
var func:Function = {
args: [for(a in values) {
value: a.expr,
type: a.type,
opt: false,
name: a.name
}],
expr: {
pos: Context.currentPos(),
expr: EBlock([])
}
};
var funcField:Field = {
pos: Context.currentPos(),
name: "recycle",
kind: FFun(func),
access: [APublic]
};
var funcField:Field = {
pos: Context.currentPos(),
name: "recycle",
kind: FFun(func),
access: [APublic]
};
fields.push(funcField);
fields.push(funcField);
var p = new Printer();
switch(func.expr.expr) {
case EBlock(exprs):
// add a "set this" expr for each variable
for(v in values) {
var name = v.name;
exprs.push({
pos: Context.currentPos(),
expr: EBinop(OpAssign, {
pos: Context.currentPos(),
expr: EField({
pos: Context.currentPos(),
expr: EConst(CIdent("this"))
}, name)
}, {
pos: Context.currentPos(),
expr: EConst(CIdent(name))
})
});
}
var p = new Printer();
switch(func.expr.expr) {
case EBlock(exprs):
// add a "set this" expr for each variable
for(v in values) {
var name = v.name;
exprs.push({
pos: Context.currentPos(),
expr: EBinop(OpAssign, {
pos: Context.currentPos(),
expr: EField({
pos: Context.currentPos(),
expr: EConst(CIdent("this"))
}, name)
}, {
pos: Context.currentPos(),
expr: EConst(CIdent(name))
})
});
}
// add a "set this" expr to reset each private/hidden variables
for(v in hiddenValues) {
var name = v.name;
exprs.push({
pos: Context.currentPos(),
expr: EBinop(OpAssign, {
pos: Context.currentPos(),
expr: EField({
pos: Context.currentPos(),
expr: EConst(CIdent("this"))
}, name)
}, v.expr)
});
}
// add a "set this" expr to reset each private/hidden variables
for(v in hiddenValues) {
var name = v.name;
exprs.push({
pos: Context.currentPos(),
expr: EBinop(OpAssign, {
pos: Context.currentPos(),
expr: EField({
pos: Context.currentPos(),
expr: EConst(CIdent("this"))
}, name)
}, v.expr)
});
}
exprs.push(macro return this);
exprs.insert(0, macro recycleBase());
default:
// nothing
}
exprs.push(macro return this);
exprs.insert(0, macro recycleBase());
default:
// nothing
}
return fields;
}
return fields;
}
}
typedef EventVar = {
var name:String;
var type:ComplexType;
var expr:Expr;
var name:String;
var type:ComplexType;
var expr:Expr;
}
#end
+39 -39
View File
@@ -8,47 +8,47 @@ using StringTools;
* Macro used in the options class to add getters for the SOLO keybinds.
*/
class OptionsMacro {
public static function build():Array<Field> {
var fields = Context.getBuildFields();
public static function build():Array<Field> {
var fields = Context.getBuildFields();
for(f in fields) {
switch(f.kind) {
case FProp(get, set, t, e):
if (f.name.startsWith('SOLO_') && get == "get" && set == "null") {
// Auto-create getters for solo (P1/P2) keybinds
var name = f.name.substr(5);
var getterName = 'get_SOLO_$name';
var ponename = 'P1_$name';
var ptwoname = 'P2_$name';
var newFuncExpr:Expr = macro {
var a:Array<FlxKey> = [];
for(e in ${{
pos: Context.currentPos(),
expr: EConst(CIdent(ponename))
}}) a.push(e);
for(e in ${{
pos: Context.currentPos(),
expr: EConst(CIdent(ptwoname))
}}) a.push(e);
return a;
};
for(f in fields) {
switch(f.kind) {
case FProp(get, set, t, e):
if (f.name.startsWith('SOLO_') && get == "get" && set == "null") {
// Auto-create getters for solo (P1/P2) keybinds
var name = f.name.substr(5);
var getterName = 'get_SOLO_$name';
var ponename = 'P1_$name';
var ptwoname = 'P2_$name';
var newFuncExpr:Expr = macro {
var a:Array<FlxKey> = [];
for(e in ${{
pos: Context.currentPos(),
expr: EConst(CIdent(ponename))
}}) a.push(e);
for(e in ${{
pos: Context.currentPos(),
expr: EConst(CIdent(ptwoname))
}}) a.push(e);
return a;
};
fields.push({
name: getterName,
kind: FFun({
expr: newFuncExpr,
args: []
}),
pos: Context.currentPos(),
access: [APrivate, AStatic, AInline]
});
}
default:
// nothing
}
}
fields.push({
name: getterName,
kind: FFun({
expr: newFuncExpr,
args: []
}),
pos: Context.currentPos(),
access: [APrivate, AStatic, AInline]
});
}
default:
// nothing
}
}
return fields;
}
return fields;
}
}
#end
+36 -36
View File
@@ -9,47 +9,47 @@ import haxe.macro.Expr;
* Macros containing additional help functions to expand HScript capabilities.
*/
class ScriptsMacro {
public static function addAdditionalClasses() {
Compiler.include("flixel");
Compiler.include("away3d");
Compiler.include("flx3d");
#if (sys && !web)
Compiler.include("sys");
#end
public static function addAdditionalClasses() {
Compiler.include("flixel");
Compiler.include("away3d");
Compiler.include("flx3d");
#if (sys && !web)
Compiler.include("sys");
#end
Compiler.include("DateTools");
Compiler.include("EReg");
Compiler.include("Lambda");
Compiler.include("StringBuf");
Compiler.include("haxe.crypto");
Compiler.include("haxe.display");
Compiler.include("haxe.exceptions");
#if !web
Compiler.include("haxe.extern");
#end
Compiler.include("DateTools");
Compiler.include("EReg");
Compiler.include("Lambda");
Compiler.include("StringBuf");
Compiler.include("haxe.crypto");
Compiler.include("haxe.display");
Compiler.include("haxe.exceptions");
#if !web
Compiler.include("haxe.extern");
#end
Compiler.include("scripting");
Compiler.include("scripting");
// FOR ABSTRACTS
Compiler.addGlobalMetadata('haxe.xml', '@:build(hscript.UsingHandler.build())');
}
// FOR ABSTRACTS
Compiler.addGlobalMetadata('haxe.xml', '@:build(hscript.UsingHandler.build())');
}
public static function build():Array<Field> {
var fields:Array<Field> = Context.getBuildFields();
public static function build():Array<Field> {
var fields:Array<Field> = Context.getBuildFields();
for(f in fields) {
switch(f.kind) {
case FFun(func):
if (f.access == null) f.access = [];
if (f.access.contains(AInline))
f.access.remove(AInline);
f.access.push(ADynamic);
default:
// do nothing u piece of shit
}
}
for(f in fields) {
switch(f.kind) {
case FFun(func):
if (f.access == null) f.access = [];
if (f.access.contains(AInline))
f.access.remove(AInline);
f.access.push(ADynamic);
default:
// do nothing u piece of shit
}
}
return fields;
}
return fields;
}
}
#end
+10 -10
View File
@@ -14,18 +14,18 @@ import haxe.macro.Compiler;
* `<haxeflag name="--macro" value="funkin.macros.StdDeprecationsRemover.init()" />`
*/
class StdDeprecationsRemover {
public static function init() {
Compiler.addGlobalMetadata('Std', '@:build(funkin.macros.StdDeprecationsRemover.build())');
}
public static function init() {
Compiler.addGlobalMetadata('Std', '@:build(funkin.macros.StdDeprecationsRemover.build())');
}
public static function build():Array<Field> {
var fields:Array<Field> = Context.getBuildFields();
public static function build():Array<Field> {
var fields:Array<Field> = Context.getBuildFields();
for(f in fields)
if (f.name == "is")
f.meta = [for(e in f.meta) if (e.name != ":deprecated") e];
for(f in fields)
if (f.name == "is")
f.meta = [for(e in f.meta) if (e.name != ":deprecated") e];
return fields;
}
return fields;
}
}
#end
+30 -30
View File
@@ -6,48 +6,48 @@ import flixel.text.FlxText;
import funkin.ui.FunkinText;
class BetaWarningState extends MusicBeatState {
var titleAlphabet:Alphabet;
var disclaimer:FunkinText;
var titleAlphabet:Alphabet;
var disclaimer:FunkinText;
var transitioning:Bool = false;
var transitioning:Bool = false;
public override function create() {
super.create();
public override function create() {
super.create();
titleAlphabet = new Alphabet(0, 0, "WARNING", true);
titleAlphabet.screenCenter(X);
add(titleAlphabet);
titleAlphabet = new Alphabet(0, 0, "WARNING", true);
titleAlphabet.screenCenter(X);
add(titleAlphabet);
disclaimer = new FunkinText(16, titleAlphabet.y + titleAlphabet.height + 10, FlxG.width - 32, "", 32);
disclaimer.alignment = CENTER;
disclaimer.applyMarkup("This engine is still in a beta state. That means *majority of the features* are either *buggy* or *non finished*. If you find any bug, please report them to the Codename Engine GitHub.\n\nPress ENTER to continue",
[
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFF4444), "*")
]
);
add(disclaimer);
disclaimer = new FunkinText(16, titleAlphabet.y + titleAlphabet.height + 10, FlxG.width - 32, "", 32);
disclaimer.alignment = CENTER;
disclaimer.applyMarkup("This engine is still in a beta state. That means *majority of the features* are either *buggy* or *non finished*. If you find any bug, please report them to the Codename Engine GitHub.\n\nPress ENTER to continue",
[
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFF4444), "*")
]
);
add(disclaimer);
var off = Std.int((FlxG.height - (disclaimer.y + disclaimer.height)) / 2);
disclaimer.y += off;
titleAlphabet.y += off;
}
var off = Std.int((FlxG.height - (disclaimer.y + disclaimer.height)) / 2);
disclaimer.y += off;
titleAlphabet.y += off;
}
public override function update(elapsed:Float) {
super.update(elapsed);
public override function update(elapsed:Float) {
super.update(elapsed);
if (controls.ACCEPT && transitioning) {
FlxG.camera.stopFX(); FlxG.camera.visible = false;
goToTitle();
}
if (controls.ACCEPT && !transitioning) {
transitioning = true;
CoolUtil.playMenuSFX(CONFIRM);
FlxG.camera.flash(FlxColor.WHITE, 1, function() {
FlxG.camera.fade(FlxColor.BLACK, 2.5, false, goToTitle);
});
}
}
if (controls.ACCEPT && !transitioning) {
transitioning = true;
CoolUtil.playMenuSFX(CONFIRM);
FlxG.camera.flash(FlxColor.WHITE, 1, function() {
FlxG.camera.fade(FlxColor.BLACK, 2.5, false, goToTitle);
});
}
}
private function goToTitle() {
FlxTransitionableState.skipNextTransIn = FlxTransitionableState.skipNextTransOut = true;
+7 -7
View File
@@ -348,7 +348,7 @@ class FreeplayState extends MusicBeatState
if (event.cancelled) return;
curSelected = event.value;
if (event.playMenuSFX) CoolUtil.playMenuSFX(SCROLL, 0.7);
if (event.playMenuSFX) CoolUtil.playMenuSFX(SCROLL, 0.7);
changeDiff(0, true);
@@ -382,9 +382,9 @@ class FreeplayState extends MusicBeatState
}
class FreeplaySonglist {
public var songs:Array<ChartMetaData> = [];
public var songs:Array<ChartMetaData> = [];
public function new() {}
public function new() {}
public function getSongsFromSource(source:funkin.system.AssetsLibraryList.AssetSource, useTxt:Bool = true) {
var path:String = Paths.txt('freeplaySonglist');
@@ -403,12 +403,12 @@ class FreeplaySonglist {
return true;
}
public static function get(useTxt:Bool = true) {
var songList = new FreeplaySonglist();
public static function get(useTxt:Bool = true) {
var songList = new FreeplaySonglist();
if (songList.getSongsFromSource(MODS, useTxt))
songList.getSongsFromSource(SOURCE, useTxt);
return songList;
}
return songList;
}
}
+54 -54
View File
@@ -7,72 +7,72 @@ import sys.FileSystem;
import flixel.tweens.FlxTween;
class ModSwitchMenu extends MusicBeatSubstate {
var mods:Array<String> = [];
var alphabets:FlxTypedGroup<Alphabet>;
var curSelected:Int = 0;
var mods:Array<String> = [];
var alphabets:FlxTypedGroup<Alphabet>;
var curSelected:Int = 0;
public override function create() {
super.create();
public override function create() {
super.create();
var bg = new FlxSprite(0, 0).makeGraphic(1, 1, 0xFF000000);
bg.scale.set(FlxG.width, FlxG.height);
bg.updateHitbox();
bg.scrollFactor.set();
add(bg);
var bg = new FlxSprite(0, 0).makeGraphic(1, 1, 0xFF000000);
bg.scale.set(FlxG.width, FlxG.height);
bg.updateHitbox();
bg.scrollFactor.set();
add(bg);
bg.alpha = 0;
FlxTween.tween(bg, {alpha: 0.5}, 0.25, {ease: FlxEase.cubeOut});
bg.alpha = 0;
FlxTween.tween(bg, {alpha: 0.5}, 0.25, {ease: FlxEase.cubeOut});
for(modFolder in FileSystem.readDirectory(ModsFolder.modsPath)) {
if (FileSystem.isDirectory('${ModsFolder.modsPath}${modFolder}')) {
mods.push(modFolder);
} else {
var ext = Path.extension(modFolder).toLowerCase();
switch(ext) {
case 'zip':
// is a zip mod!!
mods.push(Path.withoutExtension(modFolder));
}
}
}
for(modFolder in FileSystem.readDirectory(ModsFolder.modsPath)) {
if (FileSystem.isDirectory('${ModsFolder.modsPath}${modFolder}')) {
mods.push(modFolder);
} else {
var ext = Path.extension(modFolder).toLowerCase();
switch(ext) {
case 'zip':
// is a zip mod!!
mods.push(Path.withoutExtension(modFolder));
}
}
}
alphabets = new FlxTypedGroup<Alphabet>();
for(mod in mods) {
var a = new Alphabet(0, 0, mod, true);
a.isMenuItem = true;
a.scrollFactor.set();
alphabets.add(a);
}
add(alphabets);
changeSelection(0, true);
}
alphabets = new FlxTypedGroup<Alphabet>();
for(mod in mods) {
var a = new Alphabet(0, 0, mod, true);
a.isMenuItem = true;
a.scrollFactor.set();
alphabets.add(a);
}
add(alphabets);
changeSelection(0, true);
}
public override function update(elapsed:Float) {
super.update(elapsed);
public override function update(elapsed:Float) {
super.update(elapsed);
changeSelection((controls.DOWN_P ? 1 : 0) + (controls.UP_P ? -1 : 0));
changeSelection((controls.DOWN_P ? 1 : 0) + (controls.UP_P ? -1 : 0));
if (controls.ACCEPT) {
ModsFolder.switchMod(mods[curSelected]);
close();
}
if (controls.ACCEPT) {
ModsFolder.switchMod(mods[curSelected]);
close();
}
if (controls.BACK)
close();
}
if (controls.BACK)
close();
}
public function changeSelection(change:Int, force:Bool = false) {
if (change == 0 && !force) return;
public function changeSelection(change:Int, force:Bool = false) {
if (change == 0 && !force) return;
curSelected = FlxMath.wrap(curSelected + change, 0, alphabets.length-1);
curSelected = FlxMath.wrap(curSelected + change, 0, alphabets.length-1);
CoolUtil.playMenuSFX(SCROLL, 0.7);
CoolUtil.playMenuSFX(SCROLL, 0.7);
for(k=>alphabet in alphabets.members) {
alphabet.alpha = 0.6;
alphabet.targetY = k - curSelected;
}
alphabets.members[curSelected].alpha = 1;
}
for(k=>alphabet in alphabets.members) {
alphabet.alpha = 0.6;
alphabet.targetY = k - curSelected;
}
alphabets.members[curSelected].alpha = 1;
}
}
#end
+1 -1
View File
@@ -41,7 +41,7 @@ class PauseSubState extends MusicBeatSubstate
pauseScript = Script.create(Paths.script(script));
pauseScript.setParent(this);
pauseScript.load();
pauseScript.load();
var event = EventManager.get(PauseCreationEvent).recycle('breakfast', menuItems);
pauseScript.call('create', [event]);
+1 -1
View File
@@ -323,7 +323,7 @@ class TitleState extends MusicBeatState
}
}
} catch(e) {
Logs.trace('Failed to load titlescreen XML: $e', ERROR);
Logs.trace('Failed to load titlescreen XML: $e', ERROR);
}
}
#end
+95 -95
View File
@@ -15,120 +15,120 @@ import funkin.menus.MainMenuState;
using funkin.utils.BitmapUtil;
class CreditsCodename extends OptionsScreen {
public var contributorsSprites:Array<FlxSprite> = [];
public var contributorsAvatars:Array<FlxGraphic> = [];
public var contributorsColors:Array<FlxColor> = [];
public var avatarLoadListId:Int = 0;
public var contributors:Array<GitHubContributor>;
public var contributorsSprites:Array<FlxSprite> = [];
public var contributorsAvatars:Array<FlxGraphic> = [];
public var contributorsColors:Array<FlxColor> = [];
public var avatarLoadListId:Int = 0;
public var contributors:Array<GitHubContributor>;
public var interpColor:FlxInterpolateColor;
public var interpColor:FlxInterpolateColor;
public var errorMessage:String = "";
public var errorMessage:String = "";
public override function create() {
contributors = GitHub.getContributors("YoshiCrafter29", "CodenameEngine", function(e) {
errorMessage = Std.string(e);
});
public override function create() {
contributors = GitHub.getContributors("YoshiCrafter29", "CodenameEngine", function(e) {
errorMessage = Std.string(e);
});
var totalContributions = 0;
var totalContributions = 0;
for(c in contributors)
totalContributions += c.contributions;
for(c in contributors)
totalContributions += c.contributions;
options = [for(c in contributors) new TextOption(
c.login,
'Total Contributions: ${c.contributions} / ${totalContributions} (${FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)}%) - Select to open GitHub account',
function() {
// open the link
CoolUtil.openURL(c.html_url);
})];
options = [for(c in contributors) new TextOption(
c.login,
'Total Contributions: ${c.contributions} / ${totalContributions} (${FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)}%) - Select to open GitHub account',
function() {
// open the link
CoolUtil.openURL(c.html_url);
})];
super.create();
interpColor = new FlxInterpolateColor(bg.color);
}
super.create();
interpColor = new FlxInterpolateColor(bg.color);
}
public override function changeSelection(change:Int) {
if (contributors.length <= 0)
return;
super.changeSelection(change);
}
public override function changeSelection(change:Int) {
if (contributors.length <= 0)
return;
super.changeSelection(change);
}
public override function createAdditional() {
if (contributors.length <= 0) {
var t = new FunkinText(0, 0, FlxG.width, 'Could not load engine contributors.\nMake sure you\'re connected to the Internet.\n\n${errorMessage}\n\nPress BACK to go back.', 40, true);
t.alignment = CENTER;
t.borderSize *= 1.75;
t.screenCenter();
public override function createAdditional() {
if (contributors.length <= 0) {
var t = new FunkinText(0, 0, FlxG.width, 'Could not load engine contributors.\nMake sure you\'re connected to the Internet.\n\n${errorMessage}\n\nPress BACK to go back.', 40, true);
t.alignment = CENTER;
t.borderSize *= 1.75;
t.screenCenter();
var bg = new FlxSprite(0, 0).makeGraphic(1, 1, 0xFF000000);
bg.alpha = 0.5;
bg.scale.set(FlxG.width - 80, t.height + 40);
bg.updateHitbox();
bg.screenCenter();
add(bg);
add(t);
return;
}
var bg = new FlxSprite(0, 0).makeGraphic(1, 1, 0xFF000000);
bg.alpha = 0.5;
bg.scale.set(FlxG.width - 80, t.height + 40);
bg.updateHitbox();
bg.screenCenter();
add(bg);
add(t);
return;
}
for(k=>c in contributors) {
var spr = new FlxSprite(0, (OptionsScreen.optionHeight * (k+0.5)) - 48);
spr.antialiasing = true;
spr.setUnstretchedGraphicSize(96, 96, false);
spr.updateHitbox();
spr.shader = new CustomShader('engine/circleProfilePicture');
contributorsSprites.push(spr);
add(spr);
}
for(k=>c in contributors) {
var spr = new FlxSprite(0, (OptionsScreen.optionHeight * (k+0.5)) - 48);
spr.antialiasing = true;
spr.setUnstretchedGraphicSize(96, 96, false);
spr.updateHitbox();
spr.shader = new CustomShader('engine/circleProfilePicture');
contributorsSprites.push(spr);
add(spr);
}
// asynchronous pfp loading
Main.execAsync(function() {
for(k=>c in contributors) {
var bytes = GitHub.__requestBytesOnGitHubServers('${c.avatar_url}&size=96');
var bmap = BitmapData.fromBytes(bytes);
var color = bmap.getMostPresentSaturatedColor();
contributorsAvatars.push(FlxG.bitmap.add(bmap, false, 'GITHUB-USER:${c.login}'));
contributorsColors.push(color);
if (destroyed) return;
}
});
}
// asynchronous pfp loading
Main.execAsync(function() {
for(k=>c in contributors) {
var bytes = GitHub.__requestBytesOnGitHubServers('${c.avatar_url}&size=96');
var bmap = BitmapData.fromBytes(bytes);
var color = bmap.getMostPresentSaturatedColor();
contributorsAvatars.push(FlxG.bitmap.add(bmap, false, 'GITHUB-USER:${c.login}'));
contributorsColors.push(color);
if (destroyed) return;
}
});
}
public override function update(elapsed:Float) {
super.update(elapsed);
public override function update(elapsed:Float) {
super.update(elapsed);
if (contributors.length <= 0) {
if (controls.BACK)
exit();
return;
}
if (contributors.length <= 0) {
if (controls.BACK)
exit();
return;
}
if (avatarLoadListId < contributorsAvatars.length) {
for(i in avatarLoadListId...contributorsAvatars.length) {
var v = contributorsSprites[i];
v.loadGraphic(contributorsAvatars[i]);
v.setUnstretchedGraphicSize(96, 96, false);
v.updateHitbox();
}
avatarLoadListId = contributorsAvatars.length;
}
if (avatarLoadListId < contributorsAvatars.length) {
for(i in avatarLoadListId...contributorsAvatars.length) {
var v = contributorsSprites[i];
v.loadGraphic(contributorsAvatars[i]);
v.setUnstretchedGraphicSize(96, 96, false);
v.updateHitbox();
}
avatarLoadListId = contributorsAvatars.length;
}
for(k=>spr in contributorsSprites) {
var alpha = options[k];
spr.x = alpha.x - 10;
}
for(k=>spr in contributorsSprites) {
var alpha = options[k];
spr.x = alpha.x - 10;
}
interpColor.fpsLerpTo(contributorsColors[curSelected], 0.0625);
bg.color = interpColor.color;
}
interpColor.fpsLerpTo(contributorsColors[curSelected], 0.0625);
bg.color = interpColor.color;
}
public override function destroy() {
super.destroy();
}
public override function destroy() {
super.destroy();
}
public override function exit() {
FlxTransitionableState.skipNextTransOut = true;
FlxG.switchState(new CreditsMain());
}
public override function exit() {
FlxTransitionableState.skipNextTransOut = true;
FlxG.switchState(new CreditsMain());
}
}
+16 -16
View File
@@ -5,21 +5,21 @@ import funkin.options.OptionsScreen;
import funkin.options.type.*;
class CreditsMain extends OptionsScreen {
public override function create() {
options = [
// TODO: Custom Credits
new TextOption("Codename Engine", "Select this to see all of the contributors of the engine!", function() {
FlxTransitionableState.skipNextTransIn = FlxTransitionableState.skipNextTransOut = true;
FlxG.switchState(new CreditsCodename());
}),
new TextOption("Friday Night Funkin'", "Select this to open the itch.io page of the original game to donate!", function() {
CoolUtil.openURL("https://ninja-muffin24.itch.io/funkin");
})
];
super.create();
}
public override function create() {
options = [
// TODO: Custom Credits
new TextOption("Codename Engine", "Select this to see all of the contributors of the engine!", function() {
FlxTransitionableState.skipNextTransIn = FlxTransitionableState.skipNextTransOut = true;
FlxG.switchState(new CreditsCodename());
}),
new TextOption("Friday Night Funkin'", "Select this to open the itch.io page of the original game to donate!", function() {
CoolUtil.openURL("https://ninja-muffin24.itch.io/funkin");
})
];
super.create();
}
public override function exit() {
FlxG.switchState(new MainMenuState());
}
public override function exit() {
FlxG.switchState(new MainMenuState());
}
}
+26 -26
View File
@@ -6,34 +6,34 @@ import lime.utils.AssetLibrary;
* Used to prevent crashes
*/
class ModdableAssetsFolder extends ModsFolderLibrary {
public var oldLibrary:AssetLibrary;
public var oldLibrary:AssetLibrary;
public override function exists(id:String, type:String) {
if (!id.startsWith("assets/") && !exists('assets/$id', type))
return oldLibrary.exists(id, type);
return super.exists(id, type);
}
public override function exists(id:String, type:String) {
if (!id.startsWith("assets/") && !exists('assets/$id', type))
return oldLibrary.exists(id, type);
return super.exists(id, type);
}
public override function getAsset(id:String, type:String) {
if (!id.startsWith("assets/")) {
var possibleReplacement = getAsset('assets/$id', type);
if (possibleReplacement != null)
return possibleReplacement;
return oldLibrary.getAsset(id, type);
}
return super.getAsset(id, type);
}
public override function getAsset(id:String, type:String) {
if (!id.startsWith("assets/")) {
var possibleReplacement = getAsset('assets/$id', type);
if (possibleReplacement != null)
return possibleReplacement;
return oldLibrary.getAsset(id, type);
}
return super.getAsset(id, type);
}
public function new(folder:String, libName:String, oldLib:AssetLibrary) {
super(folder, libName);
oldLibrary = oldLib;
trace(Type.getClassName(Type.getClass(oldLibrary)));
}
public function new(folder:String, libName:String, oldLib:AssetLibrary) {
super(folder, libName);
oldLibrary = oldLib;
trace(Type.getClassName(Type.getClass(oldLibrary)));
}
private override function __parseAsset(asset:String):Bool {
var prefix = 'assets/';
if (!asset.startsWith(prefix)) return false;
_parsedAsset = asset.substr(prefix.length);
return true;
}
private override function __parseAsset(asset:String):Bool {
var prefix = 'assets/';
if (!asset.startsWith(prefix)) return false;
_parsedAsset = asset.substr(prefix.length);
return true;
}
}
+10 -10
View File
@@ -22,20 +22,20 @@ import sys.FileSystem;
using StringTools;
interface ModsAssetLibrary {
public var prefix:String;
public var libName:String;
public var prefix:String;
public var libName:String;
#if MOD_SUPPORT
public var _parsedAsset:String;
#if MOD_SUPPORT
public var _parsedAsset:String;
private function getAssetPath():String;
private function getAssetPath():String;
private function __isCacheValid(cache:Map<String, Dynamic>, asset:String, isLocal:Bool = false):Bool;
private function __isCacheValid(cache:Map<String, Dynamic>, asset:String, isLocal:Bool = false):Bool;
private function __parseAsset(asset:String):Bool;
private function __parseAsset(asset:String):Bool;
public function getFiles(folder:String):Array<String>;
public function getFiles(folder:String):Array<String>;
public function getFolders(folder:String):Array<String>;
#end
public function getFolders(folder:String):Array<String>;
#end
}
+93 -93
View File
@@ -19,115 +19,115 @@ import haxe.io.Path;
using StringTools;
class ModsFolder {
/**
* INTERNAL - Only use when editing source mods!!
*/
@:dox(hide) public static var onModSwitch:FlxTypedSignal<String->Void> = new FlxTypedSignal<String->Void>();
/**
* INTERNAL - Only use when editing source mods!!
*/
@:dox(hide) public static var onModSwitch:FlxTypedSignal<String->Void> = new FlxTypedSignal<String->Void>();
/**
* Current mod folder. Will affect `Paths`.
*/
public static var currentModFolder:String = null;
/**
* Map all loaded mods' folder libraries.
*/
public static var loadedMods:Map<String, lime.utils.AssetLibrary> = [];
/**
* Path to the `mods` folder.
*/
public static var modsPath:String = "./mods/";
/**
* Current mod folder. Will affect `Paths`.
*/
public static var currentModFolder:String = null;
/**
* Map all loaded mods' folder libraries.
*/
public static var loadedMods:Map<String, lime.utils.AssetLibrary> = [];
/**
* Path to the `mods` folder.
*/
public static var modsPath:String = "./mods/";
/**
* Initialises `mods` folder by adding callbacks and such.
*/
public static function init() {
/**
* Initialises `mods` folder by adding callbacks and such.
*/
public static function init() {
}
}
/**
* Loads a mod with the specified name.
* @param modName Name of the mod
* @param force Whenever the mod should be reloaded if it has already been loaded
*/
public static function loadMod(mod:String, force:Bool = false) {
#if MOD_SUPPORT
if (mod == null) return null; // may be loading base game
/**
* Loads a mod with the specified name.
* @param modName Name of the mod
* @param force Whenever the mod should be reloaded if it has already been loaded
*/
public static function loadMod(mod:String, force:Bool = false) {
#if MOD_SUPPORT
if (mod == null) return null; // may be loading base game
if (FileSystem.exists('${modsPath}$mod.zip'))
return loadedMods[mod] = loadLibraryFromZip('mods/$mod'.toLowerCase(), '${modsPath}$mod.zip', force);
else
return loadedMods[mod] = loadLibraryFromFolder('mods/$mod'.toLowerCase(), '${modsPath}$mod', force);
if (FileSystem.exists('${modsPath}$mod.zip'))
return loadedMods[mod] = loadLibraryFromZip('mods/$mod'.toLowerCase(), '${modsPath}$mod.zip', force);
else
return loadedMods[mod] = loadLibraryFromFolder('mods/$mod'.toLowerCase(), '${modsPath}$mod', force);
#else
return null;
#end
}
#else
return null;
#end
}
/**
* Switches mod - unloads all the other mods, then load this one.
* @param libName
*/
public static function switchMod(mod:String) {
unloadMod(ModsFolder.currentModFolder);
Options.lastLoadedMod = ModsFolder.currentModFolder = mod;
Options.save();
if (ModsFolder.currentModFolder == null) return;
/**
* Switches mod - unloads all the other mods, then load this one.
* @param libName
*/
public static function switchMod(mod:String) {
unloadMod(ModsFolder.currentModFolder);
Options.lastLoadedMod = ModsFolder.currentModFolder = mod;
Options.save();
if (ModsFolder.currentModFolder == null) return;
Paths.assetsTree.addLibrary(loadMod(ModsFolder.currentModFolder));
Paths.assetsTree.addLibrary(loadMod(ModsFolder.currentModFolder));
Main.refreshAssets();
onModSwitch.dispatch(ModsFolder.currentModFolder);
if (FlxG.sound.music != null && FlxG.sound.music.playing)
FlxG.sound.music.fadeOut(0.25, 0, function(t) {
FlxG.sound.music.stop();
});
DiscordUtil.reloadJsonData();
TitleState.initialized = false;
FlxG.switchState(new TitleState());
}
Main.refreshAssets();
onModSwitch.dispatch(ModsFolder.currentModFolder);
if (FlxG.sound.music != null && FlxG.sound.music.playing)
FlxG.sound.music.fadeOut(0.25, 0, function(t) {
FlxG.sound.music.stop();
});
DiscordUtil.reloadJsonData();
TitleState.initialized = false;
FlxG.switchState(new TitleState());
}
public static function unloadMod(mod:String) {
if (mod == null) return;
public static function unloadMod(mod:String) {
if (mod == null) return;
Paths.assetsTree.clearCache();
FlxG.bitmap.reset();
Paths.assetsTree.removeLibrary(loadedMods[mod]);
Assets.unloadLibrary('mods/$mod'.toLowerCase());
Paths.assetsTree.clearCache();
FlxG.bitmap.reset();
Paths.assetsTree.removeLibrary(loadedMods[mod]);
Assets.unloadLibrary('mods/$mod'.toLowerCase());
loadedMods[mod] = null;
}
loadedMods[mod] = null;
}
public static function prepareLibrary(libName:String, force:Bool = false) {
if (Assets.hasLibrary(libName)) {
if (force)
Assets.unloadLibrary(libName);
else
return null;
}
public static function prepareLibrary(libName:String, force:Bool = false) {
if (Assets.hasLibrary(libName)) {
if (force)
Assets.unloadLibrary(libName);
else
return null;
}
var assets:AssetManifest = new AssetManifest();
assets.name = libName;
assets.version = 2;
assets.libraryArgs = [];
assets.assets = [];
var assets:AssetManifest = new AssetManifest();
assets.name = libName;
assets.version = 2;
assets.libraryArgs = [];
assets.assets = [];
return AssetLibrary.fromManifest(assets);
}
return AssetLibrary.fromManifest(assets);
}
public static function prepareModLibrary(libName:String, lib:ModsAssetLibrary, force:Bool = false) {
var openLib = prepareLibrary(libName, force);
lib.prefix = 'assets/';
@:privateAccess
openLib.__proxy = cast(lib, lime.utils.AssetLibrary);
Assets.registerLibrary(libName, openLib);
return openLib;
}
public static function prepareModLibrary(libName:String, lib:ModsAssetLibrary, force:Bool = false) {
var openLib = prepareLibrary(libName, force);
lib.prefix = 'assets/';
@:privateAccess
openLib.__proxy = cast(lib, lime.utils.AssetLibrary);
Assets.registerLibrary(libName, openLib);
return openLib;
}
public static function loadLibraryFromFolder(libName:String, folder:String, force:Bool = false) {
return prepareModLibrary(libName, new ModsFolderLibrary(folder, libName), force);
}
public static function loadLibraryFromFolder(libName:String, folder:String, force:Bool = false) {
return prepareModLibrary(libName, new ModsFolderLibrary(folder, libName), force);
}
public static function loadLibraryFromZip(libName:String, zipPath:String, force:Bool = false) {
return prepareModLibrary(libName, new ZipFolderLibrary(zipPath, libName), force);
}
public static function loadLibraryFromZip(libName:String, zipPath:String, force:Bool = false) {
return prepareModLibrary(libName, new ZipFolderLibrary(zipPath, libName), force);
}
}
+78 -78
View File
@@ -16,27 +16,27 @@ import sys.FileSystem;
using StringTools;
class ModsFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
public var folderPath:String;
public var libName:String;
public var useImageCache:Bool = true;
public var prefix = 'assets/';
public var folderPath:String;
public var libName:String;
public var useImageCache:Bool = true;
public var prefix = 'assets/';
public function new(folderPath:String, libName:String) {
this.folderPath = folderPath;
this.libName = libName;
this.prefix = 'assets/$libName/';
super();
}
public function new(folderPath:String, libName:String) {
this.folderPath = folderPath;
this.libName = libName;
this.prefix = 'assets/$libName/';
super();
}
#if MOD_SUPPORT
private var editedTimes:Map<String, Float> = [];
public var _parsedAsset:String = null;
#if MOD_SUPPORT
private var editedTimes:Map<String, Float> = [];
public var _parsedAsset:String = null;
public function getEditedTime(asset:String):Null<Float> {
return editedTimes[asset];
}
public function getEditedTime(asset:String):Null<Float> {
return editedTimes[asset];
}
public override function getAudioBuffer(id:String):AudioBuffer {
public override function getAudioBuffer(id:String):AudioBuffer {
if (!exists(id, "SOUND"))
return null;
var path = getAssetPath();
@@ -44,9 +44,9 @@ class ModsFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
var e = AudioBuffer.fromFile(path);
// LimeAssets.cache.audio.set('$libName:$id', e);
return e;
}
}
public override function getBytes(id:String):Bytes {
public override function getBytes(id:String):Bytes {
if (!exists(id, "BINARY"))
return null;
var path = getAssetPath();
@@ -54,18 +54,18 @@ class ModsFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
var e = Bytes.fromFile(path);
cachedBytes.set(id, e);
return e;
}
}
public override function getFont(id:String):Font {
public override function getFont(id:String):Font {
if (!exists(id, "FONT"))
return null;
var path = getAssetPath();
editedTimes[id] = FileSystem.stat(path).mtime.getTime();
var e = Font.fromFile(path);
return e;
}
}
public override function getImage(id:String):Image {
public override function getImage(id:String):Image {
if (!exists(id, "IMAGE"))
return null;
var path = getAssetPath();
@@ -73,69 +73,69 @@ class ModsFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
var e = Image.fromFile(path);
return e;
}
}
public override function getPath(id:String):String {
if (!__parseAsset(id)) return null;
return getAssetPath();
}
public override function getPath(id:String):String {
if (!__parseAsset(id)) return null;
return getAssetPath();
}
public inline function getFolders(folder:String):Array<String>
return __getFiles(folder, true);
public inline function getFolders(folder:String):Array<String>
return __getFiles(folder, true);
public inline function getFiles(folder:String):Array<String>
return __getFiles(folder, false);
public inline function getFiles(folder:String):Array<String>
return __getFiles(folder, false);
public function __getFiles(folder:String, folders:Bool = false) {
if (!folder.endsWith("/")) folder = folder + "/";
if (!__parseAsset(folder)) return [];
var path = getAssetPath();
try {
var result:Array<String> = [];
for(e in FileSystem.readDirectory(path))
if (FileSystem.isDirectory('$path$e') == folders)
result.push(e);
return result;
} catch(e) {
// woops!!
}
return [];
}
public function __getFiles(folder:String, folders:Bool = false) {
if (!folder.endsWith("/")) folder = folder + "/";
if (!__parseAsset(folder)) return [];
var path = getAssetPath();
try {
var result:Array<String> = [];
for(e in FileSystem.readDirectory(path))
if (FileSystem.isDirectory('$path$e') == folders)
result.push(e);
return result;
} catch(e) {
// woops!!
}
return [];
}
public override function exists(asset:String, type:String):Bool {
if(!__parseAsset(asset)) return false;
return FileSystem.exists(getAssetPath());
}
public override function exists(asset:String, type:String):Bool {
if(!__parseAsset(asset)) return false;
return FileSystem.exists(getAssetPath());
}
private function getAssetPath() {
return '$folderPath/$_parsedAsset';
}
private function getAssetPath() {
return '$folderPath/$_parsedAsset';
}
private function __isCacheValid(cache:Map<String, Dynamic>, asset:String, isLocalCache:Bool = false) {
if (!editedTimes.exists(asset))
return false;
if (editedTimes[asset] == null || editedTimes[asset] < FileSystem.stat(getPath(asset)).mtime.getTime()) {
// destroy already existing to prevent memory leak!!!
var asset = cache[asset];
if (asset != null) {
switch(Type.getClass(asset)) {
case lime.graphics.Image:
trace("getting rid of image cause replaced");
cast(asset, lime.graphics.Image);
}
}
return false;
}
private function __isCacheValid(cache:Map<String, Dynamic>, asset:String, isLocalCache:Bool = false) {
if (!editedTimes.exists(asset))
return false;
if (editedTimes[asset] == null || editedTimes[asset] < FileSystem.stat(getPath(asset)).mtime.getTime()) {
// destroy already existing to prevent memory leak!!!
var asset = cache[asset];
if (asset != null) {
switch(Type.getClass(asset)) {
case lime.graphics.Image:
trace("getting rid of image cause replaced");
cast(asset, lime.graphics.Image);
}
}
return false;
}
if (!isLocalCache) asset = '$libName:$asset';
if (!isLocalCache) asset = '$libName:$asset';
return cache.exists(asset) && cache[asset] != null;
}
return cache.exists(asset) && cache[asset] != null;
}
private function __parseAsset(asset:String):Bool {
if (!asset.startsWith(prefix)) return false;
_parsedAsset = asset.substr(prefix.length);
return true;
}
#end
private function __parseAsset(asset:String):Bool {
if (!asset.startsWith(prefix)) return false;
_parsedAsset = asset.substr(prefix.length);
return true;
}
#end
}
+119 -119
View File
@@ -25,64 +25,64 @@ import haxe.zip.Entry;
#end
class ZipFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
public var zipPath:String;
public var libName:String;
public var useImageCache:Bool = false;
public var prefix = 'assets/';
public var zipPath:String;
public var libName:String;
public var useImageCache:Bool = false;
public var prefix = 'assets/';
#if MOD_SUPPORT
public var zip:Reader;
public var assets:Map<String, Entry> = [];
#end
#if MOD_SUPPORT
public var zip:Reader;
public var assets:Map<String, Entry> = [];
#end
public function new(zipPath:String, libName:String) {
this.zipPath = zipPath;
this.libName = libName;
this.prefix = 'assets/$libName/';
public function new(zipPath:String, libName:String) {
this.zipPath = zipPath;
this.libName = libName;
this.prefix = 'assets/$libName/';
#if MOD_SUPPORT
zip = new Reader(File.read(zipPath, true));
var entries = zip.read();
for(entry in entries) {
assets[entry.fileName.toLowerCase()] = entry;
}
#end
#if MOD_SUPPORT
zip = new Reader(File.read(zipPath, true));
var entries = zip.read();
for(entry in entries) {
assets[entry.fileName.toLowerCase()] = entry;
}
#end
super();
}
super();
}
#if MOD_SUPPORT
public var _parsedAsset:String;
#if MOD_SUPPORT
public var _parsedAsset:String;
public override function getAudioBuffer(id:String):AudioBuffer {
if (__isCacheValid(LimeAssets.cache.audio, id))
return LimeAssets.cache.audio.get('$libName:$id');
else {
if (!exists(id, "SOUND")) {
Log.error('ZipFolderLibrary: Audio Buffer at $id does not exist.');
return null;
}
var e = AudioBuffer.fromBytes(unzip(assets[_parsedAsset]));
return e;
}
}
public override function getAudioBuffer(id:String):AudioBuffer {
if (__isCacheValid(LimeAssets.cache.audio, id))
return LimeAssets.cache.audio.get('$libName:$id');
else {
if (!exists(id, "SOUND")) {
Log.error('ZipFolderLibrary: Audio Buffer at $id does not exist.');
return null;
}
var e = AudioBuffer.fromBytes(unzip(assets[_parsedAsset]));
return e;
}
}
public override function getBytes(id:String):Bytes {
if (__isCacheValid(cachedBytes, id, true))
return cachedBytes.get(id);
else {
if (!exists(id, "BINARY")) {
Log.error('ZipFolderLibrary: Bytes at $id does not exist.');
return null;
}
var e = Bytes.fromBytes(unzip(assets[_parsedAsset]));
cachedBytes.set(id, e);
return e;
}
}
public override function getBytes(id:String):Bytes {
if (__isCacheValid(cachedBytes, id, true))
return cachedBytes.get(id);
else {
if (!exists(id, "BINARY")) {
Log.error('ZipFolderLibrary: Bytes at $id does not exist.');
return null;
}
var e = Bytes.fromBytes(unzip(assets[_parsedAsset]));
cachedBytes.set(id, e);
return e;
}
}
public static function unzip(f:Entry) {
public static function unzip(f:Entry) {
if (!f.compressed)
return f.data;
var c = new haxe.zip.Uncompress(-15);
@@ -97,86 +97,86 @@ class ZipFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
return f.data;
}
public override function getFont(id:String):Font {
if (__isCacheValid(LimeAssets.cache.font, id))
return LimeAssets.cache.font.get('$libName:$id');
else {
if (!exists(id, "FONT")) {
Log.error('ZipFolderLibrary: Font at $id does not exist.');
return null;
}
var e = Font.fromBytes(unzip(assets[_parsedAsset]));
return e;
}
}
public override function getFont(id:String):Font {
if (__isCacheValid(LimeAssets.cache.font, id))
return LimeAssets.cache.font.get('$libName:$id');
else {
if (!exists(id, "FONT")) {
Log.error('ZipFolderLibrary: Font at $id does not exist.');
return null;
}
var e = Font.fromBytes(unzip(assets[_parsedAsset]));
return e;
}
}
public override function getImage(id:String):Image {
if (useImageCache && __isCacheValid(LimeAssets.cache.image, id))
return LimeAssets.cache.image.get('$libName:$id');
else {
if (!exists(id, "IMAGE")) {
Log.error('ZipFolderLibrary: Image at $id does not exist.');
return null;
}
var e = Image.fromBytes(unzip(assets[_parsedAsset]));
if (useImageCache) cachedImages.set(id, e);
return e;
}
}
public override function getImage(id:String):Image {
if (useImageCache && __isCacheValid(LimeAssets.cache.image, id))
return LimeAssets.cache.image.get('$libName:$id');
else {
if (!exists(id, "IMAGE")) {
Log.error('ZipFolderLibrary: Image at $id does not exist.');
return null;
}
var e = Image.fromBytes(unzip(assets[_parsedAsset]));
if (useImageCache) cachedImages.set(id, e);
return e;
}
}
public function __parseAsset(asset:String):Bool {
if (!asset.startsWith(prefix)) return false;
_parsedAsset = asset.substr(prefix.length).toLowerCase();
return true;
}
public function __parseAsset(asset:String):Bool {
if (!asset.startsWith(prefix)) return false;
_parsedAsset = asset.substr(prefix.length).toLowerCase();
return true;
}
public function __isCacheValid(cache:Map<String, Dynamic>, asset:String, isLocal:Bool = false) {
if (cache.exists(isLocal ? '$libName:$asset': asset)) return true;
return false;
}
public function __isCacheValid(cache:Map<String, Dynamic>, asset:String, isLocal:Bool = false) {
if (cache.exists(isLocal ? '$libName:$asset': asset)) return true;
return false;
}
public override function exists(asset:String, type:String):Bool {
if(!__parseAsset(asset)) return false;
public override function exists(asset:String, type:String):Bool {
if(!__parseAsset(asset)) return false;
return assets[_parsedAsset] != null;
}
return assets[_parsedAsset] != null;
}
private function getAssetPath() {
return _parsedAsset;
}
private function getAssetPath() {
return _parsedAsset;
}
public function getFiles(folder:String):Array<String> {
var content:Array<String> = [];
public function getFiles(folder:String):Array<String> {
var content:Array<String> = [];
if (!folder.endsWith("/")) folder = folder + "/";
if (!__parseAsset(folder)) return [];
if (!folder.endsWith("/")) folder = folder + "/";
if (!__parseAsset(folder)) return [];
@:privateAccess
for(k=>e in assets) {
if (k.toLowerCase().startsWith(_parsedAsset)) {
var fileName = k.substr(_parsedAsset.length);
if (!fileName.contains("/"))
content.push(fileName);
}
}
return content;
}
@:privateAccess
for(k=>e in assets) {
if (k.toLowerCase().startsWith(_parsedAsset)) {
var fileName = k.substr(_parsedAsset.length);
if (!fileName.contains("/"))
content.push(fileName);
}
}
return content;
}
public function getFolders(folder:String):Array<String> {
var content:Array<String> = [];
public function getFolders(folder:String):Array<String> {
var content:Array<String> = [];
if (!folder.endsWith("/")) folder = folder + "/";
if (!__parseAsset(folder)) return [];
if (!folder.endsWith("/")) folder = folder + "/";
if (!__parseAsset(folder)) return [];
@:privateAccess
for(k=>e in assets) {
if (k.toLowerCase().startsWith(_parsedAsset)) {
var fileName = k.substr(_parsedAsset.length);
if (fileName.contains("/"))
content.push(fileName.split("/")[0]);
}
}
return content;
}
#end
@:privateAccess
for(k=>e in assets) {
if (k.toLowerCase().startsWith(_parsedAsset)) {
var fileName = k.substr(_parsedAsset.length);
if (fileName.contains("/"))
content.push(fileName.split("/")[0]);
}
}
return content;
}
#end
}
+119 -119
View File
@@ -4,11 +4,11 @@ import funkin.windows.WindowsAPI.MessageBoxIcon;
#if windows
@:buildXml('
<target id="haxe">
<lib name="dwmapi.lib" if="windows" />
<lib name="shell32.lib" if="windows" />
<lib name="gdi32.lib" if="windows" />
<lib name="ole32.lib" if="windows" />
<lib name="uxtheme.lib" if="windows" />
<lib name="dwmapi.lib" if="windows" />
<lib name="shell32.lib" if="windows" />
<lib name="gdi32.lib" if="windows" />
<lib name="ole32.lib" if="windows" />
<lib name="uxtheme.lib" if="windows" />
</target>
')
@@ -28,86 +28,86 @@ import funkin.windows.WindowsAPI.MessageBoxIcon;
#include <uxtheme.h>
#define SAFE_RELEASE(punk) \\
if ((punk) != NULL) \\
{ (punk)->Release(); (punk) = NULL; }
if ((punk) != NULL) \\
{ (punk)->Release(); (punk) = NULL; }
static long lastDefId = 0;
class AudioFixClient : public IMMNotificationClient {
LONG _cRef;
IMMDeviceEnumerator *_pEnumerator;
LONG _cRef;
IMMDeviceEnumerator *_pEnumerator;
public:
AudioFixClient() :
_cRef(1),
_pEnumerator(NULL)
{
HRESULT result = CoCreateInstance(__uuidof(MMDeviceEnumerator),
NULL, CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator),
(void**)&_pEnumerator);
if (result == S_OK) {
_pEnumerator->RegisterEndpointNotificationCallback(this);
}
}
public:
AudioFixClient() :
_cRef(1),
_pEnumerator(NULL)
{
HRESULT result = CoCreateInstance(__uuidof(MMDeviceEnumerator),
NULL, CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator),
(void**)&_pEnumerator);
if (result == S_OK) {
_pEnumerator->RegisterEndpointNotificationCallback(this);
}
}
~AudioFixClient()
{
SAFE_RELEASE(_pEnumerator);
}
~AudioFixClient()
{
SAFE_RELEASE(_pEnumerator);
}
ULONG STDMETHODCALLTYPE AddRef()
{
return InterlockedIncrement(&_cRef);
}
ULONG STDMETHODCALLTYPE AddRef()
{
return InterlockedIncrement(&_cRef);
}
ULONG STDMETHODCALLTYPE Release()
{
ULONG ulRef = InterlockedDecrement(&_cRef);
if (0 == ulRef)
{
delete this;
}
return ulRef;
}
ULONG STDMETHODCALLTYPE Release()
{
ULONG ulRef = InterlockedDecrement(&_cRef);
if (0 == ulRef)
{
delete this;
}
return ulRef;
}
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid, VOID **ppvInterface)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid, VOID **ppvInterface)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId)
{
return S_OK;
};
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId)
{
return S_OK;
};
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(
LPCWSTR pwstrDeviceId,
DWORD dwNewState)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(
LPCWSTR pwstrDeviceId,
DWORD dwNewState)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(
LPCWSTR pwstrDeviceId,
const PROPERTYKEY key)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(
LPCWSTR pwstrDeviceId,
const PROPERTYKEY key)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(
EDataFlow flow, ERole role,
LPCWSTR pwstrDeviceId)
{
::funkin::_hx_system::Main_obj::audioDisconnected = true;
return S_OK;
};
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(
EDataFlow flow, ERole role,
LPCWSTR pwstrDeviceId)
{
::funkin::_hx_system::Main_obj::audioDisconnected = true;
return S_OK;
};
};
AudioFixClient *curAudioFix;
@@ -115,69 +115,69 @@ AudioFixClient *curAudioFix;
@:dox(hide)
class Windows {
public static var __audioChangeCallback:Void->Void = function() {
trace("test");
};
public static var __audioChangeCallback:Void->Void = function() {
trace("test");
};
@:functionCode('
if (!curAudioFix) curAudioFix = new AudioFixClient();
')
public static function registerAudio() {
funkin.system.Main.audioDisconnected = false;
}
@:functionCode('
if (!curAudioFix) curAudioFix = new AudioFixClient();
')
public static function registerAudio() {
funkin.system.Main.audioDisconnected = false;
}
@:functionCode('
int darkMode = enable ? 1 : 0;
HWND window = GetActiveWindow();
if (S_OK != DwmSetWindowAttribute(window, 19, &darkMode, sizeof(darkMode))) {
DwmSetWindowAttribute(window, 20, &darkMode, sizeof(darkMode));
}
')
public static function setDarkMode(enable:Bool) {}
@:functionCode('
int darkMode = enable ? 1 : 0;
HWND window = GetActiveWindow();
if (S_OK != DwmSetWindowAttribute(window, 19, &darkMode, sizeof(darkMode))) {
DwmSetWindowAttribute(window, 20, &darkMode, sizeof(darkMode));
}
')
public static function setDarkMode(enable:Bool) {}
@:functionCode('
// https://stackoverflow.com/questions/15543571/allocconsole-not-displaying-cout
@:functionCode('
// https://stackoverflow.com/questions/15543571/allocconsole-not-displaying-cout
if (!AllocConsole())
return;
if (!AllocConsole())
return;
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
')
public static function allocConsole() {
}
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
')
public static function allocConsole() {
}
@:functionCode('
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(console, color);
')
public static function setConsoleColors(color:Int) {
@:functionCode('
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(console, color);
')
public static function setConsoleColors(color:Int) {
}
}
@:functionCode('
system("CLS");
std::cout<< "" <<std::flush;
')
public static function clearScreen() {
@:functionCode('
system("CLS");
std::cout<< "" <<std::flush;
')
public static function clearScreen() {
}
}
@:functionCode('
MessageBox(GetActiveWindow(), message, caption, icon | MB_SETFOREGROUND);
')
public static function showMessageBox(caption:String, message:String, icon:MessageBoxIcon = MSG_WARNING) {
@:functionCode('
MessageBox(GetActiveWindow(), message, caption, icon | MB_SETFOREGROUND);
')
public static function showMessageBox(caption:String, message:String, icon:MessageBoxIcon = MSG_WARNING) {
}
}
@:functionCode('
SetProcessDPIAware();
')
public static function registerAsDPICompatible() {}
@:functionCode('
SetProcessDPIAware();
')
public static function registerAsDPICompatible() {}
@:functionCode("
// simple but effective code
+93 -93
View File
@@ -10,114 +10,114 @@ import funkin.options.categories.*;
import funkin.options.TreeMenu;
class OptionsMenu extends TreeMenu {
public static var mainOptions:Array<OptionCategory> = [
{
name: 'Controls',
desc: 'Change Controls for Player 1 and Player 2!',
state: null,
substate: funkin.options.keybinds.KeybindsOptions
},
{
name: 'Gameplay >',
desc: 'Change Gameplay options such as Downscroll, Scroll Speed, Naughtyness...',
state: GameplayOptions
},
{
name: 'Appearance >',
desc: 'Change Appearance options such as Flashing menus...',
state: AppearanceOptions
},
{
name: 'Miscellaneous >',
desc: 'Use this menu to reset save data or engine settings.',
state: MiscOptions
}
];
public static var mainOptions:Array<OptionCategory> = [
{
name: 'Controls',
desc: 'Change Controls for Player 1 and Player 2!',
state: null,
substate: funkin.options.keybinds.KeybindsOptions
},
{
name: 'Gameplay >',
desc: 'Change Gameplay options such as Downscroll, Scroll Speed, Naughtyness...',
state: GameplayOptions
},
{
name: 'Appearance >',
desc: 'Change Appearance options such as Flashing menus...',
state: AppearanceOptions
},
{
name: 'Miscellaneous >',
desc: 'Use this menu to reset save data or engine settings.',
state: MiscOptions
}
];
public override function create() {
super.create();
public override function create() {
super.create();
CoolUtil.playMenuSong();
CoolUtil.playMenuSong();
var bg:FlxSprite = new FlxSprite(-80).loadAnimatedGraphic(Paths.image('menus/menuBGBlue'));
// bg.scrollFactor.set();
var bg:FlxSprite = new FlxSprite(-80).loadAnimatedGraphic(Paths.image('menus/menuBGBlue'));
// bg.scrollFactor.set();
bg.scale.set(1.15, 1.15);
bg.updateHitbox();
bg.screenCenter();
bg.scrollFactor.set();
bg.scrollFactor.set();
bg.antialiasing = true;
add(bg);
main = new OptionsScreen("Options", "Select a category to continue.", [for(o in mainOptions) new TextOption(o.name, o.desc, function() {
if (o.substate != null) {
persistentUpdate = false;
persistentDraw = true;
if (o.substate is MusicBeatSubstate) {
openSubState(o.substate);
} else {
openSubState(Type.createInstance(o.substate, []));
}
} else {
if (o.state is OptionsScreen) {
optionsTree.add(o.state);
} else {
optionsTree.add(Type.createInstance(o.state, []));
}
}
})]);
main = new OptionsScreen("Options", "Select a category to continue.", [for(o in mainOptions) new TextOption(o.name, o.desc, function() {
if (o.substate != null) {
persistentUpdate = false;
persistentDraw = true;
if (o.substate is MusicBeatSubstate) {
openSubState(o.substate);
} else {
openSubState(Type.createInstance(o.substate, []));
}
} else {
if (o.state is OptionsScreen) {
optionsTree.add(o.state);
} else {
optionsTree.add(Type.createInstance(o.state, []));
}
}
})]);
var xmlPath = Paths.xml("config/options");
for(source in [funkin.system.AssetsLibraryList.AssetSource.SOURCE, funkin.system.AssetsLibraryList.AssetSource.MODS]) {
if (Paths.assetsTree.existsSpecific(xmlPath, "TEXT", source)) {
var access:Access = null;
try {
access = new Access(Xml.parse(Paths.assetsTree.getSpecificAsset(xmlPath, "TEXT", source)));
} catch(e) {
Logs.trace('Error while parsing options.xml: ${Std.string(e)}', ERROR);
}
var xmlPath = Paths.xml("config/options");
for(source in [funkin.system.AssetsLibraryList.AssetSource.SOURCE, funkin.system.AssetsLibraryList.AssetSource.MODS]) {
if (Paths.assetsTree.existsSpecific(xmlPath, "TEXT", source)) {
var access:Access = null;
try {
access = new Access(Xml.parse(Paths.assetsTree.getSpecificAsset(xmlPath, "TEXT", source)));
} catch(e) {
Logs.trace('Error while parsing options.xml: ${Std.string(e)}', ERROR);
}
if (access != null)
for(o in parseOptionsFromXML(access))
main.add(o);
}
}
if (access != null)
for(o in parseOptionsFromXML(access))
main.add(o);
}
}
}
}
public override function exit() {
Options.save();
Options.applySettings();
super.exit();
}
public override function exit() {
Options.save();
Options.applySettings();
super.exit();
}
/**
* XML STUFF
*/
public function parseOptionsFromXML(xml:Access):Array<OptionType> {
var options:Array<OptionType> = [];
/**
* XML STUFF
*/
public function parseOptionsFromXML(xml:Access):Array<OptionType> {
var options:Array<OptionType> = [];
for(node in xml.elements) {
if (!node.has.name) {
Logs.trace("An option node requires a name attribute.", WARNING);
continue;
}
var name = node.getAtt("name");
var desc = node.getAtt("desc").getDefault("No Description");
for(node in xml.elements) {
if (!node.has.name) {
Logs.trace("An option node requires a name attribute.", WARNING);
continue;
}
var name = node.getAtt("name");
var desc = node.getAtt("desc").getDefault("No Description");
switch(node.name) {
case "checkbox":
if (!node.has.id) {
Logs.trace("A checkbox option requires an \"id\" for option saving.", WARNING);
continue;
}
options.push(new Checkbox(name, desc, node.att.id, FlxG.save.data));
case "menu":
options.push(new TextOption(name + " >", desc, function() {
optionsTree.add(new OptionsScreen(name, desc, parseOptionsFromXML(node)));
}));
}
}
switch(node.name) {
case "checkbox":
if (!node.has.id) {
Logs.trace("A checkbox option requires an \"id\" for option saving.", WARNING);
continue;
}
options.push(new Checkbox(name, desc, node.att.id, FlxG.save.data));
case "menu":
options.push(new TextOption(name + " >", desc, function() {
optionsTree.add(new OptionsScreen(name, desc, parseOptionsFromXML(node)));
}));
}
}
return options;
}
return options;
}
}
+47 -47
View File
@@ -3,67 +3,67 @@ package funkin.options;
import funkin.options.type.OptionType;
class OptionsScreen extends FlxTypedSpriteGroup<OptionType> {
public static var optionHeight:Float = 120;
public static var optionHeight:Float = 120;
public var parent:OptionsTree;
public var parent:OptionsTree;
public var curSelected:Int = 0;
public var id:Int = 0;
public var curSelected:Int = 0;
public var id:Int = 0;
private var __firstFrame:Bool = true;
private var __firstFrame:Bool = true;
public var name:String;
public var desc:String;
public var name:String;
public var desc:String;
public function new(name:String, desc:String, ?options:Array<OptionType>) {
super();
this.name = name;
this.desc = desc;
if (options != null) for(o in options) add(o);
}
public function new(name:String, desc:String, ?options:Array<OptionType>) {
super();
this.name = name;
this.desc = desc;
if (options != null) for(o in options) add(o);
}
public override function update(elapsed:Float) {
super.update(elapsed);
public override function update(elapsed:Float) {
super.update(elapsed);
var controls = PlayerSettings.solo.controls;
var controls = PlayerSettings.solo.controls;
changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0) - FlxG.mouse.wheel);
x = id * FlxG.width;
for(k=>option in members) {
var y:Float = ((FlxG.height - optionHeight) / 2) + ((k - curSelected) * optionHeight);
changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0) - FlxG.mouse.wheel);
x = id * FlxG.width;
for(k=>option in members) {
var y:Float = ((FlxG.height - optionHeight) / 2) + ((k - curSelected) * optionHeight);
option.selected = false;
option.y = __firstFrame ? y : CoolUtil.fpsLerp(option.y, y, 0.25);
option.x = x + (-50 + (Math.abs(Math.cos((option.y + (optionHeight / 2) - (FlxG.camera.scroll.y + (FlxG.height / 2))) / (FlxG.height * 1.25) * Math.PI)) * 150));
}
if (__firstFrame) {
__firstFrame = false;
return;
}
option.selected = false;
option.y = __firstFrame ? y : CoolUtil.fpsLerp(option.y, y, 0.25);
option.x = x + (-50 + (Math.abs(Math.cos((option.y + (optionHeight / 2) - (FlxG.camera.scroll.y + (FlxG.height / 2))) / (FlxG.height * 1.25) * Math.PI)) * 150));
}
if (__firstFrame) {
__firstFrame = false;
return;
}
if (members.length > 0) {
members[curSelected].selected = true;
if (controls.ACCEPT || FlxG.mouse.justReleased)
members[curSelected].onSelect();
}
if (controls.BACK || FlxG.mouse.justReleasedRight)
close();
}
if (members.length > 0) {
members[curSelected].selected = true;
if (controls.ACCEPT || FlxG.mouse.justReleased)
members[curSelected].onSelect();
}
if (controls.BACK || FlxG.mouse.justReleasedRight)
close();
}
public function close() {
onClose(this);
}
public function close() {
onClose(this);
}
public function changeSelection(sel:Int) {
if (members.length <= 0 || sel == 0) return;
public function changeSelection(sel:Int) {
if (members.length <= 0 || sel == 0) return;
CoolUtil.playMenuSFX(SCROLL);
CoolUtil.playMenuSFX(SCROLL);
curSelected = FlxMath.wrap(curSelected + sel, 0, members.length-1);
curSelected = FlxMath.wrap(curSelected + sel, 0, members.length-1);
for(o in members)
members[curSelected].selected = true;
}
for(o in members)
members[curSelected].selected = true;
}
public dynamic function onClose(o:OptionsScreen) {}
public dynamic function onClose(o:OptionsScreen) {}
}
+57 -57
View File
@@ -2,73 +2,73 @@ package funkin.options;
import flixel.util.FlxDestroyUtil;
class OptionsTree extends FlxTypedGroup<OptionsScreen> {
public var lastMenu:OptionsScreen;
public override function new() {
super();
public var lastMenu:OptionsScreen;
public override function new() {
super();
}
}
public override function update(elapsed:Float) {
var last = members.last();
if (last != null)
last.update(elapsed);
}
public override function update(elapsed:Float) {
var last = members.last();
if (last != null)
last.update(elapsed);
}
public override function draw() {
super.draw();
if (lastMenu != null) {
lastMenu.draw();
}
}
public override function draw() {
super.draw();
if (lastMenu != null) {
lastMenu.draw();
}
}
public override function add(m:OptionsScreen) {
super.add(m);
setup(m);
clearLastMenu();
onMenuChange();
return m;
}
public override function insert(pos:Int, m:OptionsScreen) {
var last = members.last();
super.insert(pos, m);
setup(m);
if (last != members.last())
onMenuChange();
return m;
}
public override function add(m:OptionsScreen) {
super.add(m);
setup(m);
clearLastMenu();
onMenuChange();
return m;
}
public override function insert(pos:Int, m:OptionsScreen) {
var last = members.last();
super.insert(pos, m);
setup(m);
if (last != members.last())
onMenuChange();
return m;
}
public function setup(m:OptionsScreen) {
m.onClose = __subMenuClose;
m.id = members.indexOf(m);
m.parent = this;
m.update(0);
}
public function setup(m:OptionsScreen) {
m.onClose = __subMenuClose;
m.id = members.indexOf(m);
m.parent = this;
m.update(0);
}
function __subMenuClose(m:OptionsScreen) {
clearLastMenu();
lastMenu = m;
remove(m, true);
onMenuChange();
onMenuClose(m);
}
function __subMenuClose(m:OptionsScreen) {
clearLastMenu();
lastMenu = m;
remove(m, true);
onMenuChange();
onMenuClose(m);
}
public function clearLastMenu() {
if (lastMenu != null) {
lastMenu.destroy();
lastMenu = null;
}
}
public function clearLastMenu() {
if (lastMenu != null) {
lastMenu.destroy();
lastMenu = null;
}
}
public override function destroy() {
super.destroy();
lastMenu = FlxDestroyUtil.destroy(lastMenu);
}
public override function destroy() {
super.destroy();
lastMenu = FlxDestroyUtil.destroy(lastMenu);
}
public dynamic function onMenuChange() {
public dynamic function onMenuChange() {
}
}
public dynamic function onMenuClose(m:OptionsScreen) {
}
public dynamic function onMenuClose(m:OptionsScreen) {
}
}
+69 -69
View File
@@ -11,101 +11,101 @@ import funkin.options.categories.*;
class TreeMenu extends MusicBeatState {
public var main:OptionsScreen;
public var optionsTree:OptionsTree;
public var pathLabel:FunkinText;
public var pathDesc:FunkinText;
public var pathBG:FlxSprite;
public var main:OptionsScreen;
public var optionsTree:OptionsTree;
public var pathLabel:FunkinText;
public var pathDesc:FunkinText;
public var pathBG:FlxSprite;
public var lastState:Class<FlxState> = Type.getClass(FlxG.state);
public function new() {
super();
}
public function new() {
super();
}
public override function createPost() {
if (main == null) throw "\"main\" variable has not been set in extended class!";
public override function createPost() {
if (main == null) throw "\"main\" variable has not been set in extended class!";
FlxG.camera.scroll.set(-FlxG.width, 0);
FlxG.camera.scroll.set(-FlxG.width, 0);
pathLabel = new FunkinText(4, 4, FlxG.width - 8, "> Tree Menu", 32, false);
pathLabel.scrollFactor.set();
pathLabel = new FunkinText(4, 4, FlxG.width - 8, "> Tree Menu", 32, false);
pathLabel.scrollFactor.set();
pathDesc = new FunkinText(4, pathLabel.y + pathLabel.height + 2, FlxG.width - 8, "Current Tree Menu Description", 16, false);
pathDesc.scrollFactor.set();
pathDesc = new FunkinText(4, pathLabel.y + pathLabel.height + 2, FlxG.width - 8, "Current Tree Menu Description", 16, false);
pathDesc.scrollFactor.set();
pathBG = new FlxSprite().makeGraphic(1, 1, 0xFF000000);
pathBG.scale.set(FlxG.width, pathDesc.y + pathDesc.height + 2);
pathBG.updateHitbox();
pathBG.alpha = 0.25;
pathBG.scrollFactor.set();
pathBG = new FlxSprite().makeGraphic(1, 1, 0xFF000000);
pathBG.scale.set(FlxG.width, pathDesc.y + pathDesc.height + 2);
pathBG.updateHitbox();
pathBG.alpha = 0.25;
pathBG.scrollFactor.set();
optionsTree = new OptionsTree();
optionsTree.onMenuChange = onMenuChange;
optionsTree.onMenuClose = onMenuClose;
optionsTree.add(main);
optionsTree = new OptionsTree();
optionsTree.onMenuChange = onMenuChange;
optionsTree.onMenuClose = onMenuClose;
optionsTree.add(main);
add(optionsTree);
add(pathBG);
add(pathLabel);
add(pathDesc);
add(optionsTree);
add(pathBG);
add(pathLabel);
add(pathDesc);
super.createPost();
}
super.createPost();
}
public function onMenuChange() {
if (optionsTree.members.length <= 0) {
exit();
} else {
if (menuChangeTween != null)
menuChangeTween.cancel();
public function onMenuChange() {
if (optionsTree.members.length <= 0) {
exit();
} else {
if (menuChangeTween != null)
menuChangeTween.cancel();
menuChangeTween = FlxTween.tween(FlxG.camera.scroll, {x: FlxG.width * Math.max(0, (optionsTree.members.length-1))}, 1.5, {ease: menuTransitionEase, onComplete: function(t) {
optionsTree.clearLastMenu();
menuChangeTween = null;
}});
menuChangeTween = FlxTween.tween(FlxG.camera.scroll, {x: FlxG.width * Math.max(0, (optionsTree.members.length-1))}, 1.5, {ease: menuTransitionEase, onComplete: function(t) {
optionsTree.clearLastMenu();
menuChangeTween = null;
}});
var t = "";
for(o in optionsTree.members)
t += '${o.name} > ';
pathLabel.text = t;
var t = "";
for(o in optionsTree.members)
t += '${o.name} > ';
pathLabel.text = t;
pathDesc.text = optionsTree.members.last().desc;
pathBG.scale.set(FlxG.width, pathDesc.y + pathDesc.height + 2);
pathBG.updateHitbox();
}
}
pathDesc.text = optionsTree.members.last().desc;
pathBG.scale.set(FlxG.width, pathDesc.y + pathDesc.height + 2);
pathBG.updateHitbox();
}
}
public function exit() {
FlxG.switchState((lastState != null) ? Type.createInstance(lastState, []) : new MainMenuState());
}
public function exit() {
FlxG.switchState((lastState != null) ? Type.createInstance(lastState, []) : new MainMenuState());
}
public function onMenuClose(m:OptionsScreen) {
CoolUtil.playMenuSFX(CANCEL);
}
public function onMenuClose(m:OptionsScreen) {
CoolUtil.playMenuSFX(CANCEL);
}
var menuChangeTween:FlxTween;
public override function update(elapsed:Float) {
super.update(elapsed);
var menuChangeTween:FlxTween;
public override function update(elapsed:Float) {
super.update(elapsed);
// in case path gets so long it goes offscreen
pathLabel.x = lerp(pathLabel.x, Math.max(0, FlxG.width - 4 - pathLabel.width), 0.125);
}
// in case path gets so long it goes offscreen
pathLabel.x = lerp(pathLabel.x, Math.max(0, FlxG.width - 4 - pathLabel.width), 0.125);
}
public static inline function menuTransitionEase(e:Float)
return FlxEase.quintInOut(FlxEase.cubeOut(e));
public static inline function menuTransitionEase(e:Float)
return FlxEase.quintInOut(FlxEase.cubeOut(e));
}
typedef OptionCategory = {
var name:String;
var desc:String;
var state:OneOfTwo<OptionsScreen, Class<OptionsScreen>>;
var ?substate:OneOfTwo<MusicBeatSubstate, Class<MusicBeatSubstate>>;
var name:String;
var desc:String;
var state:OneOfTwo<OptionsScreen, Class<OptionsScreen>>;
var ?substate:OneOfTwo<MusicBeatSubstate, Class<MusicBeatSubstate>>;
}
typedef OptionTypeDef = {
var type:Class<OptionType>;
var args:Array<Dynamic>;
var type:Class<OptionType>;
var args:Array<Dynamic>;
}
@@ -1,27 +1,27 @@
package funkin.options.categories;
class AppearanceOptions extends OptionsScreen {
public override function new() {
super("Appearance", "Change Appearance options such as Flashing menus...");
add(new Checkbox(
"Antialiasing",
"If unchecked, will disable antialiasing on every sprite. Can boost performances at the cost of sharper, more pixely sprites",
"antialiasing"));
add(new Checkbox(
"Pixel Perfect Effect",
"If checked, Week 6 will have a pixel perfect effect to it enabled, aligning every pixel on the screen.",
"week6PixelPerfect"));
add(new Checkbox(
"Flashing Menu",
"If unchecked, will disable menu flashing when you select an option in the Main Menu, and other flashs will be slower",
"flashingMenu"));
add(new Checkbox(
"Low Memory Mode",
"If checked, will disable certain background elements in stages to reduce memory usage.",
"lowMemoryMode"));
add(new Checkbox(
"Auto Pause",
"If checked, switching windows will pause the game",
"autoPause"));
}
public override function new() {
super("Appearance", "Change Appearance options such as Flashing menus...");
add(new Checkbox(
"Antialiasing",
"If unchecked, will disable antialiasing on every sprite. Can boost performances at the cost of sharper, more pixely sprites",
"antialiasing"));
add(new Checkbox(
"Pixel Perfect Effect",
"If checked, Week 6 will have a pixel perfect effect to it enabled, aligning every pixel on the screen.",
"week6PixelPerfect"));
add(new Checkbox(
"Flashing Menu",
"If unchecked, will disable menu flashing when you select an option in the Main Menu, and other flashs will be slower",
"flashingMenu"));
add(new Checkbox(
"Low Memory Mode",
"If checked, will disable certain background elements in stages to reduce memory usage.",
"lowMemoryMode"));
add(new Checkbox(
"Auto Pause",
"If checked, switching windows will pause the game",
"autoPause"));
}
}
@@ -1,23 +1,23 @@
package funkin.options.categories;
class GameplayOptions extends OptionsScreen {
public override function new() {
super("Gameplay", 'Change Gameplay options such as Downscroll, Scroll Speed, Naughtyness...');
add(new Checkbox(
"Downscroll",
"If checked, notes will go from up to down instead of down to up, like if they were falling",
"downscroll"));
add(new Checkbox(
"Ghost Tapping",
"If unchecked, trying to hit any strum that have no note that can be hit will cause a miss.",
"ghostTapping"));
add(new Checkbox(
"Naughtyness",
"If unchecked, will censor Week 7 cutscenes",
"naughtyness"));
add(new Checkbox(
"Camera Zoom on Beat",
"If unchecked, will disable camera zooming every 4 beats",
"camZoomOnBeat"));
}
public override function new() {
super("Gameplay", 'Change Gameplay options such as Downscroll, Scroll Speed, Naughtyness...');
add(new Checkbox(
"Downscroll",
"If checked, notes will go from up to down instead of down to up, like if they were falling",
"downscroll"));
add(new Checkbox(
"Ghost Tapping",
"If unchecked, trying to hit any strum that have no note that can be hit will cause a miss.",
"ghostTapping"));
add(new Checkbox(
"Naughtyness",
"If unchecked, will censor Week 7 cutscenes",
"naughtyness"));
add(new Checkbox(
"Camera Zoom on Beat",
"If unchecked, will disable camera zooming every 4 beats",
"camZoomOnBeat"));
}
}
+27 -27
View File
@@ -2,31 +2,31 @@ package funkin.options.categories;
class MiscOptions extends OptionsScreen {
public override function new() {
super("Miscellaneous", "Use this menu to reset save data or engine settings.");
#if UPDATE_CHECKING
add(new Checkbox(
"Enable Beta Updates",
"If checked, will also include beta (prereleases) updates in the update checking.",
"betaUpdates"));,
add(new TextOption(
"Check for Updates",
"Select this option to check for new engine updates.",
function() {
var report = funkin.updating.UpdateUtil.checkForUpdates();
if (report.newUpdate) {
FlxG.switchState(new funkin.updating.UpdateAvailableScreen(report));
} else {
CoolUtil.playMenuSFX(CANCEL);
updateDescText("No update found.");
}
}));,
#end
add(new TextOption(
"Reset Save Data",
"Select this option to reset save data. This will remove all of your highscores",
function() {
// TODO: SAVE DATA RESETTING
}));
}
public override function new() {
super("Miscellaneous", "Use this menu to reset save data or engine settings.");
#if UPDATE_CHECKING
add(new Checkbox(
"Enable Beta Updates",
"If checked, will also include beta (prereleases) updates in the update checking.",
"betaUpdates"));,
add(new TextOption(
"Check for Updates",
"Select this option to check for new engine updates.",
function() {
var report = funkin.updating.UpdateUtil.checkForUpdates();
if (report.newUpdate) {
FlxG.switchState(new funkin.updating.UpdateAvailableScreen(report));
} else {
CoolUtil.playMenuSFX(CANCEL);
updateDescText("No update found.");
}
}));,
#end
add(new TextOption(
"Reset Save Data",
"Select this option to reset save data. This will remove all of your highscores",
function() {
// TODO: SAVE DATA RESETTING
}));
}
}
@@ -7,32 +7,32 @@ import flixel.util.FlxColor;
import flixel.input.keyboard.FlxKey;
class ChangeKeybindSubState extends MusicBeatSubstate {
var callback:FlxKey->Void;
var cancelCallback:Void->Void;
var callback:FlxKey->Void;
var cancelCallback:Void->Void;
var stillPressed:Bool = true;
public override function new(callback:FlxKey->Void, cancelCallback:Void->Void) {
this.callback = callback;
this.cancelCallback = cancelCallback;
super();
}
var stillPressed:Bool = true;
public override function new(callback:FlxKey->Void, cancelCallback:Void->Void) {
this.callback = callback;
this.cancelCallback = cancelCallback;
super();
}
public override function update(elapsed:Float) {
super.update(elapsed);
if (stillPressed && controls.ACCEPT)
return;
stillPressed = false;
public override function update(elapsed:Float) {
super.update(elapsed);
if (stillPressed && controls.ACCEPT)
return;
stillPressed = false;
var key:FlxKey = FlxG.keys.firstJustPressed();
if (cast(key, Int) <= 0) return;
var key:FlxKey = FlxG.keys.firstJustPressed();
if (cast(key, Int) <= 0) return;
if (key == ESCAPE && !FlxG.keys.pressed.SHIFT) {
close();
cancelCallback();
return;
}
close();
callback(key);
return;
}
if (key == ESCAPE && !FlxG.keys.pressed.SHIFT) {
close();
cancelCallback();
return;
}
close();
callback(key);
return;
}
}
@@ -9,95 +9,95 @@ import flixel.input.keyboard.FlxKey;
using StringTools;
class KeybindSetting extends FlxTypedSpriteGroup<FlxSprite> {
public var title:Alphabet;
public var bind1:Alphabet;
public var bind2:Alphabet;
public var icon:FlxSprite;
public var title:Alphabet;
public var bind1:Alphabet;
public var bind2:Alphabet;
public var icon:FlxSprite;
public var changingKeybind:Int = -1;
public var p2Selected:Bool = false;
public var value:String;
public var changingKeybind:Int = -1;
public var p2Selected:Bool = false;
public var value:String;
public var option1:Null<FlxKey>;
public var option2:Null<FlxKey>;
public function new(x:Float, y:Float, name:String, value:String, ?sparrowIcon:String, ?sparrowAnim:String) {
super();
this.value = value;
title = new Alphabet(0, 0, name, true);
add(title);
public var option1:Null<FlxKey>;
public var option2:Null<FlxKey>;
public function new(x:Float, y:Float, name:String, value:String, ?sparrowIcon:String, ?sparrowAnim:String) {
super();
this.value = value;
title = new Alphabet(0, 0, name, true);
add(title);
var controlArrayP1:Array<FlxKey> = Reflect.field(Options, 'P1_${value}');
var controlArrayP2:Array<FlxKey> = Reflect.field(Options, 'P2_${value}');
var controlArrayP1:Array<FlxKey> = Reflect.field(Options, 'P1_${value}');
var controlArrayP2:Array<FlxKey> = Reflect.field(Options, 'P2_${value}');
option1 = controlArrayP1[0];
option2 = controlArrayP2[0];
option1 = controlArrayP1[0];
option2 = controlArrayP2[0];
for(i in 1...3) {
var b = null;
if (i == 1)
b = bind1 = new Alphabet(0, 0, "", false);
else
b = bind2 = new Alphabet(0, 0, "", false);
for(i in 1...3) {
var b = null;
if (i == 1)
b = bind1 = new Alphabet(0, 0, "", false);
else
b = bind2 = new Alphabet(0, 0, "", false);
b.setPosition(FlxG.width * (0.25 * (i+1)) - x, -60);
add(b);
}
updateText();
b.setPosition(FlxG.width * (0.25 * (i+1)) - x, -60);
add(b);
}
updateText();
if (sparrowIcon != null) {
icon = new FlxSprite();
icon.frames = Paths.getFrames(sparrowIcon);
icon.antialiasing = true;
icon.animation.addByPrefix('icon', sparrowAnim, 24, true);
icon.animation.play('icon');
icon.setGraphicSize(75, 75);
icon.updateHitbox();
var min = Math.min(icon.scale.x, icon.scale.y);
icon.scale.set(min, min);
add(icon);
if (sparrowIcon != null) {
icon = new FlxSprite();
icon.frames = Paths.getFrames(sparrowIcon);
icon.antialiasing = true;
icon.animation.addByPrefix('icon', sparrowAnim, 24, true);
icon.animation.play('icon');
icon.setGraphicSize(75, 75);
icon.updateHitbox();
var min = Math.min(icon.scale.x, icon.scale.y);
icon.scale.set(min, min);
add(icon);
title.setPosition(100, 0);
}
title.setPosition(100, 0);
}
setPosition(x, y);
}
setPosition(x, y);
}
public override function update(elapsed:Float) {
super.update(elapsed);
bind1.alpha = (p2Selected ? 0.2 : 1) / alpha;
bind2.alpha = (p2Selected ? 1 : 0.2) / alpha;
bind1.alpha *= alpha;
bind2.alpha *= alpha;
}
public override function update(elapsed:Float) {
super.update(elapsed);
bind1.alpha = (p2Selected ? 0.2 : 1) / alpha;
bind2.alpha = (p2Selected ? 1 : 0.2) / alpha;
bind1.alpha *= alpha;
bind2.alpha *= alpha;
}
public function changeKeybind(callback:Void->Void, cancelCallback:Void->Void, p2:Bool = false) {
var flicker = FlxFlicker.flicker(this, 0, Options.flashingMenu ? 0.06 : 0.15, true, false, function(t) {});
public function changeKeybind(callback:Void->Void, cancelCallback:Void->Void, p2:Bool = false) {
var flicker = FlxFlicker.flicker(this, 0, Options.flashingMenu ? 0.06 : 0.15, true, false, function(t) {});
KeybindsOptions.instance.persistentDraw = true;
KeybindsOptions.instance.persistentUpdate = false;
KeybindsOptions.instance.persistentDraw = true;
KeybindsOptions.instance.persistentUpdate = false;
KeybindsOptions.instance.openSubState(new ChangeKeybindSubState(function(key:FlxKey) {
flicker.stop();
flicker.destroy();
if (p2)
Reflect.setField(Options, 'P2_$value', [option2 = key]);
else
Reflect.setField(Options, 'P1_$value', [option1 = key]);
updateText();
callback();
}, function() {
flicker.stop();
flicker.destroy();
if (p2)
Reflect.setField(Options, 'P2_$value', [option2 = 0]);
else
Reflect.setField(Options, 'P1_$value', [option1 = 0]);
cancelCallback();
}));
}
KeybindsOptions.instance.openSubState(new ChangeKeybindSubState(function(key:FlxKey) {
flicker.stop();
flicker.destroy();
if (p2)
Reflect.setField(Options, 'P2_$value', [option2 = key]);
else
Reflect.setField(Options, 'P1_$value', [option1 = key]);
updateText();
callback();
}, function() {
flicker.stop();
flicker.destroy();
if (p2)
Reflect.setField(Options, 'P2_$value', [option2 = 0]);
else
Reflect.setField(Options, 'P1_$value', [option1 = 0]);
cancelCallback();
}));
}
public function updateText() {
bind1.text = '${CoolUtil.keyToString(option1)}';
bind2.text = '${CoolUtil.keyToString(option2)}';
}
public function updateText() {
bind1.text = '${CoolUtil.keyToString(option1)}';
bind2.text = '${CoolUtil.keyToString(option2)}';
}
}
+216 -216
View File
@@ -8,247 +8,247 @@ import flixel.input.keyboard.FlxKey;
using StringTools;
class KeybindsOptions extends MusicBeatSubstate {
public static var instance:KeybindsOptions;
public static var instance:KeybindsOptions;
public var categories = [
{
name: 'Notes',
settings: [
{
name: '{noteLeft}',
control: 'NOTE_LEFT'
},
{
name: '{noteDown}',
control: 'NOTE_DOWN'
},
{
name: '{noteUp}',
control: 'NOTE_UP'
},
{
name: '{noteRight}',
control: 'NOTE_RIGHT'
},
]
},
{
name: 'UI',
settings: [
{
name: 'Left',
control: 'LEFT'
},
{
name: 'Down',
control: 'DOWN'
},
{
name: 'Up',
control: 'UP'
},
{
name: 'Right',
control: 'RIGHT'
},
{
name: 'Accept',
control: 'ACCEPT'
},
{
name: 'Back',
control: 'BACK'
},
{
name: 'Reset',
control: 'RESET'
},
{
name: 'Pause',
control: 'PAUSE'
},
]
},
{
name: 'Engine',
settings: [
{
name: 'Switch Mod',
control: 'SWITCHMOD'
},
]
}
];
public var categories = [
{
name: 'Notes',
settings: [
{
name: '{noteLeft}',
control: 'NOTE_LEFT'
},
{
name: '{noteDown}',
control: 'NOTE_DOWN'
},
{
name: '{noteUp}',
control: 'NOTE_UP'
},
{
name: '{noteRight}',
control: 'NOTE_RIGHT'
},
]
},
{
name: 'UI',
settings: [
{
name: 'Left',
control: 'LEFT'
},
{
name: 'Down',
control: 'DOWN'
},
{
name: 'Up',
control: 'UP'
},
{
name: 'Right',
control: 'RIGHT'
},
{
name: 'Accept',
control: 'ACCEPT'
},
{
name: 'Back',
control: 'BACK'
},
{
name: 'Reset',
control: 'RESET'
},
{
name: 'Pause',
control: 'PAUSE'
},
]
},
{
name: 'Engine',
settings: [
{
name: 'Switch Mod',
control: 'SWITCHMOD'
},
]
}
];
public var settingCam:FlxCamera;
public var settingCam:FlxCamera;
public var p2Selected:Bool = false;
public var curSelected:Int = 0;
public var canSelect:Bool = true;
public var alphabets:FlxTypedGroup<KeybindSetting>;
public var bg:FlxSprite;
public var coloredBG:FlxSprite;
public var noteColors:Array<FlxColor> = [
0xFFC24B99,
0xFF00FFFF,
0xFF12FA05,
0xFFF9393F
];
public var camFollow:FlxObject = new FlxObject(0, 0, 2, 2);
public var p2Selected:Bool = false;
public var curSelected:Int = 0;
public var canSelect:Bool = true;
public var alphabets:FlxTypedGroup<KeybindSetting>;
public var bg:FlxSprite;
public var coloredBG:FlxSprite;
public var noteColors:Array<FlxColor> = [
0xFFC24B99,
0xFF00FFFF,
0xFF12FA05,
0xFFF9393F
];
public var camFollow:FlxObject = new FlxObject(0, 0, 2, 2);
var isSubState:Bool = false;
var isSubState:Bool = false;
public override function create() {
super.create();
instance = this;
public override function create() {
super.create();
instance = this;
isSubState = FlxG.state != this;
alphabets = new FlxTypedGroup<KeybindSetting>();
isSubState = FlxG.state != this;
alphabets = new FlxTypedGroup<KeybindSetting>();
bg = new FlxSprite(-80).loadAnimatedGraphic(Paths.image(isSubState ? 'menus/menuTransparent' : 'menus/menuBGBlue'));
coloredBG = new FlxSprite(-80).loadAnimatedGraphic(Paths.image('menus/menuDesat'));
for(bg in [bg, coloredBG]) {
bg.scrollFactor.set();
bg.scale.set(1.15, 1.15);
bg.updateHitbox();
bg.screenCenter();
bg.antialiasing = true;
add(bg);
}
coloredBG.alpha = 0;
for(bg in [bg, coloredBG]) {
bg.scrollFactor.set();
bg.scale.set(1.15, 1.15);
bg.updateHitbox();
bg.screenCenter();
bg.antialiasing = true;
add(bg);
}
coloredBG.alpha = 0;
if (isSubState) {
// is substate, opened from pause menu
if (settingCam == null) {
settingCam = new FlxCamera();
settingCam.bgColor = 0xAA000000;
FlxG.cameras.add(settingCam, false);
}
cameras = [settingCam];
bg.alpha = 0;
settingCam.follow(camFollow, LOCKON, 0.125);
} else {
FlxG.camera.follow(camFollow, LOCKON, 0.125);
}
if (isSubState) {
// is substate, opened from pause menu
if (settingCam == null) {
settingCam = new FlxCamera();
settingCam.bgColor = 0xAA000000;
FlxG.cameras.add(settingCam, false);
}
cameras = [settingCam];
bg.alpha = 0;
settingCam.follow(camFollow, LOCKON, 0.125);
} else {
FlxG.camera.follow(camFollow, LOCKON, 0.125);
}
var k:Int = 0;
for(category in categories) {
k++;
var title = new Alphabet(0, k * 75, category.name, true);
title.screenCenter(X);
add(title);
var k:Int = 0;
for(category in categories) {
k++;
var title = new Alphabet(0, k * 75, category.name, true);
title.screenCenter(X);
add(title);
k++;
for(e in category.settings) {
var sparrowIcon:String = null;
var sparrowAnim:String = null;
if (e.name.startsWith('{note')) {// is actually a note!!
sparrowIcon = "game/notes/default";
sparrowAnim = switch(e.name) {
case '{noteLeft}':
"purple0";
case '{noteDown}':
"blue0";
case '{noteUp}':
"green0";
default:
"red0";
};
e.name = e.name.substring(5, e.name.length - 1);
}
k++;
for(e in category.settings) {
var sparrowIcon:String = null;
var sparrowAnim:String = null;
if (e.name.startsWith('{note')) {// is actually a note!!
sparrowIcon = "game/notes/default";
sparrowAnim = switch(e.name) {
case '{noteLeft}':
"purple0";
case '{noteDown}':
"blue0";
case '{noteUp}':
"green0";
default:
"red0";
};
e.name = e.name.substring(5, e.name.length - 1);
}
var text = new KeybindSetting(100, k * 75, e.name, e.control, sparrowIcon, sparrowAnim);
if (!isSubState)
text.bind1.color = text.bind2.color = FlxColor.BLACK;
alphabets.add(text);
k++;
}
}
add(alphabets);
add(camFollow);
}
var text = new KeybindSetting(100, k * 75, e.name, e.control, sparrowIcon, sparrowAnim);
if (!isSubState)
text.bind1.color = text.bind2.color = FlxColor.BLACK;
alphabets.add(text);
k++;
}
}
add(alphabets);
add(camFollow);
}
public override function destroy() {
super.destroy();
if (settingCam != null) FlxG.cameras.remove(settingCam);
instance = null;
}
public override function destroy() {
super.destroy();
if (settingCam != null) FlxG.cameras.remove(settingCam);
instance = null;
}
var skipThisFrame:Bool = true;
var skipThisFrame:Bool = true;
public override function update(elapsed:Float) {
super.update(elapsed);
public override function update(elapsed:Float) {
super.update(elapsed);
if (isSubState) {
bg.alpha = lerp(bg.alpha, 0.1, 0.125);
} else {
if (curSelected < 4) {
if (coloredBG.alpha == 0)
coloredBG.color = noteColors[curSelected];
else
coloredBG.color = CoolUtil.lerpColor(coloredBG.color, noteColors[curSelected], 0.0625);
if (isSubState) {
bg.alpha = lerp(bg.alpha, 0.1, 0.125);
} else {
if (curSelected < 4) {
if (coloredBG.alpha == 0)
coloredBG.color = noteColors[curSelected];
else
coloredBG.color = CoolUtil.lerpColor(coloredBG.color, noteColors[curSelected], 0.0625);
coloredBG.alpha = lerp(coloredBG.alpha, 1, 0.0625);
} else
coloredBG.alpha = lerp(coloredBG.alpha, 0, 0.0625);
}
coloredBG.alpha = lerp(coloredBG.alpha, 1, 0.0625);
} else
coloredBG.alpha = lerp(coloredBG.alpha, 0, 0.0625);
}
if (canSelect) {
if (canSelect) {
changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0));
if (controls.BACK) {
FlxTransitionableState.skipNextTransIn = true;
if (isSubState)
close();
else
FlxG.switchState(new OptionsMenu());
Options.applyKeybinds();
Options.save();
return;
}
if (controls.BACK) {
FlxTransitionableState.skipNextTransIn = true;
if (isSubState)
close();
else
FlxG.switchState(new OptionsMenu());
Options.applyKeybinds();
Options.save();
return;
}
if (controls.ACCEPT && !skipThisFrame) {
if (alphabets.members[curSelected] != null) {
canSelect = false;
CoolUtil.playMenuSFX(CONFIRM);
alphabets.members[curSelected].changeKeybind(function() {
canSelect = true;
}, function() {
canSelect = true;
}, p2Selected);
}
return;
}
if (controls.ACCEPT && !skipThisFrame) {
if (alphabets.members[curSelected] != null) {
canSelect = false;
CoolUtil.playMenuSFX(CONFIRM);
alphabets.members[curSelected].changeKeybind(function() {
canSelect = true;
}, function() {
canSelect = true;
}, p2Selected);
}
return;
}
if (controls.LEFT_P || controls.RIGHT_P) {
if (alphabets.members[curSelected] != null) {
CoolUtil.playMenuSFX(SCROLL, 0.7);
alphabets.members[curSelected].p2Selected = (p2Selected = !p2Selected);
}
}
}
super.update(elapsed);
skipThisFrame = false;
if (controls.LEFT_P || controls.RIGHT_P) {
if (alphabets.members[curSelected] != null) {
CoolUtil.playMenuSFX(SCROLL, 0.7);
alphabets.members[curSelected].p2Selected = (p2Selected = !p2Selected);
}
}
}
super.update(elapsed);
skipThisFrame = false;
}
}
public function changeSelection(change:Int) {
public function changeSelection(change:Int) {
if (change != 0) CoolUtil.playMenuSFX(SCROLL, 0.4);
curSelected = FlxMath.wrap(curSelected + change, 0, alphabets.length-1);
alphabets.forEach(function(e) {
e.alpha = 0.2;
});
if (alphabets.members[curSelected] != null) {
var alphabet = alphabets.members[curSelected];
alphabet.p2Selected = p2Selected;
alphabet.alpha = 1;
var minH = FlxG.height / 2;
var maxH = alphabets.members[alphabets.length-1].y + alphabets.members[alphabets.length-1].height - (FlxG.height / 2);
if (minH < maxH)
camFollow.setPosition(FlxG.width / 2, FlxMath.bound(alphabet.y + (alphabet.height / 2) - (35), minH, maxH));
else
camFollow.setPosition(FlxG.width / 2, FlxG.height / 2);
}
}
curSelected = FlxMath.wrap(curSelected + change, 0, alphabets.length-1);
alphabets.forEach(function(e) {
e.alpha = 0.2;
});
if (alphabets.members[curSelected] != null) {
var alphabet = alphabets.members[curSelected];
alphabet.p2Selected = p2Selected;
alphabet.alpha = 1;
var minH = FlxG.height / 2;
var maxH = alphabets.members[alphabets.length-1].y + alphabets.members[alphabets.length-1].height - (FlxG.height / 2);
if (minH < maxH)
camFollow.setPosition(FlxG.width / 2, FlxMath.bound(alphabet.y + (alphabet.height / 2) - (35), minH, maxH));
else
camFollow.setPosition(FlxG.width / 2, FlxG.height / 2);
}
}
}
+50 -50
View File
@@ -5,67 +5,67 @@ import flixel.math.FlxPoint;
@:allow()
class Checkbox extends TextOption {
public var checkbox:FlxSprite;
public var checked:Bool;
public var checkbox:FlxSprite;
public var checked:Bool;
public var parent:Dynamic;
public var parent:Dynamic;
private function get_selected() {
private function get_selected() {
}
public var optionName:String;
}
public var optionName:String;
private var offsets:Map<String, FlxPoint> = [
"checked" => FlxPoint.get(1, -1),
"unchecked" => FlxPoint.get(-12, -72),
"checking" => FlxPoint.get(12, 30)
];
private var baseCheckboxOffset:FlxPoint = FlxPoint.get();
private var offsets:Map<String, FlxPoint> = [
"checked" => FlxPoint.get(1, -1),
"unchecked" => FlxPoint.get(-12, -72),
"checking" => FlxPoint.get(12, 30)
];
private var baseCheckboxOffset:FlxPoint = FlxPoint.get();
public function new(text:String, desc:String, optionName:String, ?parent:Dynamic) {
super(text, desc, null);
public function new(text:String, desc:String, optionName:String, ?parent:Dynamic) {
super(text, desc, null);
if (parent == null)
parent = Options;
if (parent == null)
parent = Options;
this.parent = parent;
this.parent = parent;
checkbox = new FlxSprite(10, -40);
checkbox.frames = Paths.getFrames('menus/options/checkboxThingie');
checkbox.animation.addByPrefix("checked", "Check Box Selected Static", 24);
checkbox.animation.addByPrefix("unchecked", "Check Box unselected", 24);
checkbox.animation.addByPrefix("checking", "Check Box selecting animation", 24, false);
checkbox.antialiasing = true;
checkbox.scale.set(0.75, 0.75);
checkbox.updateHitbox();
add(checkbox);
checkbox = new FlxSprite(10, -40);
checkbox.frames = Paths.getFrames('menus/options/checkboxThingie');
checkbox.animation.addByPrefix("checked", "Check Box Selected Static", 24);
checkbox.animation.addByPrefix("unchecked", "Check Box unselected", 24);
checkbox.animation.addByPrefix("checking", "Check Box selecting animation", 24, false);
checkbox.antialiasing = true;
checkbox.scale.set(0.75, 0.75);
checkbox.updateHitbox();
add(checkbox);
baseCheckboxOffset.set(checkbox.offset.x, checkbox.offset.y);
baseCheckboxOffset.set(checkbox.offset.x, checkbox.offset.y);
this.optionName = optionName;
checked = Reflect.field(parent, optionName);
}
this.optionName = optionName;
checked = Reflect.field(parent, optionName);
}
public override function update(elapsed:Float) {
if (checkbox.animation.curAnim == null || (checkbox.animation.curAnim.finished || (checkbox.animation.curAnim.reversed && checkbox.animation.curAnim.curFrame <= 0))) {
checkbox.animation.play(checked ? "checked" : "unchecked", true);
}
super.update(elapsed);
var offset = offsets[checkbox.animation.curAnim.name];
if (offset != null)
checkbox.offset.set(
(offset.x * checkbox.scale.x) + baseCheckboxOffset.x,
(offset.y * checkbox.scale.y) + baseCheckboxOffset.y);
}
public override function update(elapsed:Float) {
if (checkbox.animation.curAnim == null || (checkbox.animation.curAnim.finished || (checkbox.animation.curAnim.reversed && checkbox.animation.curAnim.curFrame <= 0))) {
checkbox.animation.play(checked ? "checked" : "unchecked", true);
}
super.update(elapsed);
var offset = offsets[checkbox.animation.curAnim.name];
if (offset != null)
checkbox.offset.set(
(offset.x * checkbox.scale.x) + baseCheckboxOffset.x,
(offset.y * checkbox.scale.y) + baseCheckboxOffset.y);
}
public override function onSelect() {
Reflect.setField(parent, optionName, checked = !checked);
checkbox.animation.play("checking", true, !checked);
}
public override function onSelect() {
Reflect.setField(parent, optionName, checked = !checked);
checkbox.animation.play("checking", true, !checked);
}
public override function destroy() {
super.destroy();
for(e in offsets) e.put();
baseCheckboxOffset.put();
}
public override function destroy() {
super.destroy();
for(e in offsets) e.put();
baseCheckboxOffset.put();
}
}
+7 -7
View File
@@ -3,13 +3,13 @@ package funkin.options.type;
import funkin.game.HealthIcon;
class IconOption extends TextOption {
public var iconSpr:HealthIcon;
public var iconSpr:HealthIcon;
public function new(name:String, desc:String, icon:String, callback:Void->Void) {
super(name, desc, callback);
public function new(name:String, desc:String, icon:String, callback:Void->Void) {
super(name, desc, callback);
iconSpr = new HealthIcon(icon, false);
iconSpr.setPosition(90 - iconSpr.width, (__text.height - iconSpr.height) / 2);
add(iconSpr);
}
iconSpr = new HealthIcon(icon, false);
iconSpr.setPosition(90 - iconSpr.width, (__text.height - iconSpr.height) / 2);
add(iconSpr);
}
}
+14 -14
View File
@@ -5,24 +5,24 @@ import flixel.group.FlxSpriteGroup;
import funkin.options.OptionsScreen;
class OptionType extends FlxSpriteGroup {
public var controls(get, null):Controls;
public var selected:Bool = false;
public var desc:String;
public var controls(get, null):Controls;
public var selected:Bool = false;
public var desc:String;
public function new(desc:String) {
super();
this.desc = desc;
}
public function new(desc:String) {
super();
this.desc = desc;
}
private function get_controls() {return PlayerSettings.solo.controls;}
private function get_controls() {return PlayerSettings.solo.controls;}
public function onSelect() {
public function onSelect() {
}
}
public override function update(elapsed:Float) {
super.update(elapsed);
alpha = (selected ? 1 : 0.6);
}
public override function update(elapsed:Float) {
super.update(elapsed);
alpha = (selected ? 1 : 0.6);
}
}
+20 -20
View File
@@ -3,29 +3,29 @@ package funkin.options.type;
import flixel.effects.FlxFlicker;
class TextOption extends OptionType {
public var selectCallback:Void->Void;
public var selectCallback:Void->Void;
private var __text:Alphabet;
private var __text:Alphabet;
public var text(get, set):String;
private function get_text() {return __text.text;}
private function set_text(v:String) {return __text.text = v;}
public var text(get, set):String;
private function get_text() {return __text.text;}
private function set_text(v:String) {return __text.text = v;}
public function new(text:String, desc:String, selectCallback:Void->Void) {
super(desc);
this.selectCallback = selectCallback;
add(__text = new Alphabet(100, 20, text, true));
}
public function new(text:String, desc:String, selectCallback:Void->Void) {
super(desc);
this.selectCallback = selectCallback;
add(__text = new Alphabet(100, 20, text, true));
}
public override function draw() {
super.draw();
}
public override function onSelect() {
super.onSelect();
CoolUtil.playMenuSFX(CONFIRM);
FlxFlicker.flicker(this, 1, Options.flashingMenu ? 0.06 : 0.15, true, false, function(t) {
public override function draw() {
super.draw();
}
public override function onSelect() {
super.onSelect();
CoolUtil.playMenuSFX(CONFIRM);
FlxFlicker.flicker(this, 1, Options.flashingMenu ? 0.06 : 0.15, true, false, function(t) {
});
selectCallback();
}
});
selectCallback();
}
}
+9 -9
View File
@@ -4,15 +4,15 @@ package funkin.scripting;
* Simple class for empty scripts or scripts whose language isn't imported yet.
*/
class DummyScript extends Script {
public var variables:Map<String, Dynamic> = [];
public var variables:Map<String, Dynamic> = [];
public override function get(v:String) {return variables.get(v);}
public override function set(v:String, v2:Dynamic) {return variables.set(v, v2);}
public override function onCall(method:String, parameters:Array<Dynamic>):Dynamic {
var func = variables.get(method);
if (Reflect.isFunction(func))
return (parameters != null && parameters.length > 0) ? Reflect.callMethod(null, func, parameters) : func();
public override function get(v:String) {return variables.get(v);}
public override function set(v:String, v2:Dynamic) {return variables.set(v, v2);}
public override function onCall(method:String, parameters:Array<Dynamic>):Dynamic {
var func = variables.get(method);
if (Reflect.isFunction(func))
return (parameters != null && parameters.length > 0) ? Reflect.callMethod(null, func, parameters) : func();
return null;
}
return null;
}
}
+23 -23
View File
@@ -4,35 +4,35 @@ import flixel.FlxState;
import funkin.scripting.events.*;
class EventManager {
// map doesnt work for that
public static var eventValues:Array<CancellableEvent> = [];
public static var eventKeys:Array<Class<CancellableEvent>> = [];
// map doesnt work for that
public static var eventValues:Array<CancellableEvent> = [];
public static var eventKeys:Array<Class<CancellableEvent>> = [];
public static function get<T:CancellableEvent>(cl:Class<T>):T {
var c:Class<CancellableEvent> = cast cl;
public static function get<T:CancellableEvent>(cl:Class<T>):T {
var c:Class<CancellableEvent> = cast cl;
var index = eventKeys.indexOf(c);
if (index < 0) {
eventKeys.push(c);
eventValues.push(Type.createInstance(c, []));
return cast eventValues.last();
}
var index = eventKeys.indexOf(c);
if (index < 0) {
eventKeys.push(c);
eventValues.push(Type.createInstance(c, []));
return cast eventValues.last();
}
return cast eventValues[index];
}
return cast eventValues[index];
}
public static function reset() {
for(v in eventValues)
v.destroy();
eventValues = [];
eventKeys = [];
}
public static function reset() {
for(v in eventValues)
v.destroy();
eventValues = [];
eventKeys = [];
}
public static function init() {
public static function init() {
FlxG.signals.preStateCreate.add(onStateSwitch);
}
}
private static inline function onStateSwitch(newState:FlxState)
reset();
private static inline function onStateSwitch(newState:FlxState)
reset();
}
+90 -90
View File
@@ -9,103 +9,103 @@ import funkin.mods.ModsFolder;
* Class for THE Global Script, aka script that runs in the background at all times.
*/
class GlobalScript {
public static var script:Script;
public static var script:Script;
public static function init() {
#if MOD_SUPPORT
ModsFolder.onModSwitch.add(onModSwitch);
#end
public static function init() {
#if MOD_SUPPORT
ModsFolder.onModSwitch.add(onModSwitch);
#end
Conductor.onBeatHit.add(beatHit);
Conductor.onStepHit.add(stepHit);
Conductor.onBeatHit.add(beatHit);
Conductor.onStepHit.add(stepHit);
FlxG.signals.focusGained.add(function() {
call("focusGained");
});
FlxG.signals.focusLost.add(function() {
call("focusLost");
});
FlxG.signals.gameResized.add(function(w:Int, h:Int) {
call("gameResized", [w, h]);
});
FlxG.signals.postDraw.add(function() {
call("postDraw");
});
FlxG.signals.postGameReset.add(function() {
call("postGameReset");
});
FlxG.signals.postGameStart.add(function() {
call("postGameStart");
});
FlxG.signals.postStateSwitch.add(function() {
call("postStateSwitch");
});
FlxG.signals.postUpdate.add(function() {
call("postUpdate", [FlxG.elapsed]);
if (FlxG.keys.justPressed.F5) {
if (script != null && !(script is DummyScript)) {
Logs.trace('Reloading global script...', WARNING, YELLOW);
script.reload();
Logs.trace('Global script successfully reloaded.', WARNING, GREEN);
} else {
Logs.trace('Loading global script...', WARNING, YELLOW);
onModSwitch(#if MOD_SUPPORT ModsFolder.currentModFolder #else null #end);
if (script is DummyScript)
Logs.trace('Global script not found. Are you sure "data/global.hx" exists?', ERROR, RED);
else
Logs.trace('Global script successfully loaded.', WARNING, GREEN);
}
}
});
FlxG.signals.preDraw.add(function() {
call("preDraw");
});
FlxG.signals.preGameReset.add(function() {
call("preGameReset");
});
FlxG.signals.preGameStart.add(function() {
call("preGameStart");
});
FlxG.signals.preStateCreate.add(function(state:FlxState) {
call("preStateCreate", [state]);
});
FlxG.signals.preStateSwitch.add(function() {
call("preStateSwitch", []);
});
FlxG.signals.preUpdate.add(function() {
call("preUpdate", [FlxG.elapsed]);
call("update", [FlxG.elapsed]);
});
FlxG.signals.focusGained.add(function() {
call("focusGained");
});
FlxG.signals.focusLost.add(function() {
call("focusLost");
});
FlxG.signals.gameResized.add(function(w:Int, h:Int) {
call("gameResized", [w, h]);
});
FlxG.signals.postDraw.add(function() {
call("postDraw");
});
FlxG.signals.postGameReset.add(function() {
call("postGameReset");
});
FlxG.signals.postGameStart.add(function() {
call("postGameStart");
});
FlxG.signals.postStateSwitch.add(function() {
call("postStateSwitch");
});
FlxG.signals.postUpdate.add(function() {
call("postUpdate", [FlxG.elapsed]);
if (FlxG.keys.justPressed.F5) {
if (script != null && !(script is DummyScript)) {
Logs.trace('Reloading global script...', WARNING, YELLOW);
script.reload();
Logs.trace('Global script successfully reloaded.', WARNING, GREEN);
} else {
Logs.trace('Loading global script...', WARNING, YELLOW);
onModSwitch(#if MOD_SUPPORT ModsFolder.currentModFolder #else null #end);
if (script is DummyScript)
Logs.trace('Global script not found. Are you sure "data/global.hx" exists?', ERROR, RED);
else
Logs.trace('Global script successfully loaded.', WARNING, GREEN);
}
}
});
FlxG.signals.preDraw.add(function() {
call("preDraw");
});
FlxG.signals.preGameReset.add(function() {
call("preGameReset");
});
FlxG.signals.preGameStart.add(function() {
call("preGameStart");
});
FlxG.signals.preStateCreate.add(function(state:FlxState) {
call("preStateCreate", [state]);
});
FlxG.signals.preStateSwitch.add(function() {
call("preStateSwitch", []);
});
FlxG.signals.preUpdate.add(function() {
call("preUpdate", [FlxG.elapsed]);
call("update", [FlxG.elapsed]);
});
onModSwitch(#if MOD_SUPPORT ModsFolder.currentModFolder #else null #end);
}
onModSwitch(#if MOD_SUPPORT ModsFolder.currentModFolder #else null #end);
}
public static function event<T:CancellableEvent>(name:String, event:T):T {
if (script == null) return event;
script.call(name, [event]);
return event;
}
public static function event<T:CancellableEvent>(name:String, event:T):T {
if (script == null) return event;
script.call(name, [event]);
return event;
}
public static function call(name:String, ?args:Array<Dynamic>) {
if (script == null) return;
script.call(name, args);
}
public static function onModSwitch(newMod:String) {
call("onDestroy");
if (script != null) {
script.destroy();
script = null;
}
script = Script.create(Paths.script('data/global'));
script.load();
}
public static function call(name:String, ?args:Array<Dynamic>) {
if (script == null) return;
script.call(name, args);
}
public static function onModSwitch(newMod:String) {
call("onDestroy");
if (script != null) {
script.destroy();
script = null;
}
script = Script.create(Paths.script('data/global'));
script.load();
}
public static function beatHit(curBeat:Int) {
call("beatHit", [curBeat]);
}
public static function beatHit(curBeat:Int) {
call("beatHit", [curBeat]);
}
public static function stepHit(curStep:Int) {
call("stepHit", [curStep]);
}
public static function stepHit(curStep:Int) {
call("stepHit", [curStep]);
}
}
#end
+85 -85
View File
@@ -5,112 +5,112 @@ import openfl.Assets;
import hscript.*;
class HScript extends Script {
public var interp:Interp;
public var expr:Expr;
public var interp:Interp;
public var expr:Expr;
public override function onCreate(path:String) {
super.onCreate(path);
public override function onCreate(path:String) {
super.onCreate(path);
interp = new Interp();
interp = new Interp();
var code:String = Assets.getText(path);
var parser = new hscript.Parser();
parser.allowJSON = parser.allowMetadata = parser.allowTypes = true;
parser.preprocesorValues = Script.getDefaultPreprocessors();
interp.errorHandler = _errorHandler;
interp.staticVariables = Script.staticVariables;
interp.allowStaticVariables = interp.allowPublicVariables = true;
var code:String = Assets.getText(path);
var parser = new hscript.Parser();
parser.allowJSON = parser.allowMetadata = parser.allowTypes = true;
parser.preprocesorValues = Script.getDefaultPreprocessors();
interp.errorHandler = _errorHandler;
interp.staticVariables = Script.staticVariables;
interp.allowStaticVariables = interp.allowPublicVariables = true;
interp.variables.set("trace", Reflect.makeVarArgs((args) -> {
var v:String = Std.string(args.shift());
for (a in args) v += ", " + Std.string(a);
this.trace(v);
}));
interp.variables.set("trace", Reflect.makeVarArgs((args) -> {
var v:String = Std.string(args.shift());
for (a in args) v += ", " + Std.string(a);
this.trace(v);
}));
try {
expr = parser.parseString(code, fileName);
} catch(e:Error) {
_errorHandler(e);
} catch(e) {
_errorHandler(new Error(ECustom(e.toString()), 0, 0, fileName, 0));
}
}
try {
expr = parser.parseString(code, fileName);
} catch(e:Error) {
_errorHandler(e);
} catch(e) {
_errorHandler(new Error(ECustom(e.toString()), 0, 0, fileName, 0));
}
}
private function _errorHandler(error:Error) {
private function _errorHandler(error:Error) {
var fn = '$fileName:${error.line}: ';
var err = error.toString();
if (err.startsWith(fn)) err = err.substr(fn.length);
var fn = '$fileName:${error.line}: ';
var err = error.toString();
if (err.startsWith(fn)) err = err.substr(fn.length);
Logs.traceColored([
Logs.logText(fn, GREEN),
Logs.logText(err, RED)
], ERROR);
}
Logs.traceColored([
Logs.logText(fn, GREEN),
Logs.logText(err, RED)
], ERROR);
}
public override function setParent(parent:Dynamic) {
interp.scriptObject = parent;
}
public override function setParent(parent:Dynamic) {
interp.scriptObject = parent;
}
public override function onLoad() {
if (expr != null) {
interp.execute(expr);
call("new", []);
}
}
public override function onLoad() {
if (expr != null) {
interp.execute(expr);
call("new", []);
}
}
public override function reload() {
// save variables
public override function reload() {
// save variables
interp.allowStaticVariables = interp.allowPublicVariables = false;
var savedVariables:Map<String, Dynamic> = [];
for(k=>e in interp.variables) {
if (!Reflect.isFunction(e)) {
savedVariables[k] = e;
}
}
var oldParent = interp.scriptObject;
onCreate(path);
interp.allowStaticVariables = interp.allowPublicVariables = false;
var savedVariables:Map<String, Dynamic> = [];
for(k=>e in interp.variables) {
if (!Reflect.isFunction(e)) {
savedVariables[k] = e;
}
}
var oldParent = interp.scriptObject;
onCreate(path);
for(k=>e in Script.getDefaultVariables(this))
set(k, e);
for(k=>e in Script.getDefaultVariables(this))
set(k, e);
load();
setParent(oldParent);
load();
setParent(oldParent);
for(k=>e in savedVariables)
interp.variables.set(k, e);
for(k=>e in savedVariables)
interp.variables.set(k, e);
interp.allowStaticVariables = interp.allowPublicVariables = true;
}
interp.allowStaticVariables = interp.allowPublicVariables = true;
}
private override function onCall(funcName:String, parameters:Array<Dynamic>):Dynamic {
if (interp == null) return null;
private override function onCall(funcName:String, parameters:Array<Dynamic>):Dynamic {
if (interp == null) return null;
var func = interp.variables.get(funcName);
if (func != null && Reflect.isFunction(func))
return (parameters != null && parameters.length > 0) ? Reflect.callMethod(null, func, parameters) : func();
var func = interp.variables.get(funcName);
if (func != null && Reflect.isFunction(func))
return (parameters != null && parameters.length > 0) ? Reflect.callMethod(null, func, parameters) : func();
return null;
}
return null;
}
public override function get(val:String):Dynamic {
return interp.variables.get(val);
}
public override function get(val:String):Dynamic {
return interp.variables.get(val);
}
public override function set(val:String, value:Dynamic) {
interp.variables.set(val, value);
}
public override function set(val:String, value:Dynamic) {
interp.variables.set(val, value);
}
public override function trace(v:Dynamic) {
var posInfo = interp.posInfos();
Logs.traceColored([
Logs.logText('${fileName}:${posInfo.lineNumber}: ', GREEN),
Logs.logText(Std.isOfType(v, String) ? v : Std.string(v))
], TRACE);
}
public override function trace(v:Dynamic) {
var posInfo = interp.posInfos();
Logs.traceColored([
Logs.logText('${fileName}:${posInfo.lineNumber}: ', GREEN),
Logs.logText(Std.isOfType(v, String) ? v : Std.string(v))
], TRACE);
}
public override function setPublicMap(map:Map<String, Dynamic>) {
this.interp.publicVariables = map;
}
public override function setPublicMap(map:Map<String, Dynamic>) {
this.interp.publicVariables = map;
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
package funkin.scripting;
class ModState extends MusicBeatState {
public function new(stateName:String) {
super(true, stateName);
}
public function new(stateName:String) {
super(true, stateName);
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
package funkin.scripting;
class ModSubState extends MusicBeatSubstate {
public function new(scriptName:String) {
super(true, scriptName);
}
public function new(scriptName:String) {
super(true, scriptName);
}
}
+69 -69
View File
@@ -8,91 +8,91 @@ import hscript.IHScriptCustomBehaviour;
import flixel.util.FlxDestroyUtil;
class MultiThreadedScript implements IFlxDestroyable implements IHScriptCustomBehaviour {
var thread:#if ALLOW_MULTITHREADING Thread #else Dynamic #end;
var thread:#if ALLOW_MULTITHREADING Thread #else Dynamic #end;
/**
* Script being ran.
*/
public var script:Script;
/**
* Script being ran.
*/
public var script:Script;
private var __variables:Array<String>;
private var __variables:Array<String>;
/**
* Return value of the last call.
*/
public var returnValue:Dynamic = null;
/**
* Return value of the last call.
*/
public var returnValue:Dynamic = null;
/**
* Whenever the current call has ended.
*/
public var callEnded:Bool = true;
/**
* Whenever the current call has ended.
*/
public var callEnded:Bool = true;
public function new(path:String, ?parentScript:Script) {
script = Script.create(path);
public function new(path:String, ?parentScript:Script) {
script = Script.create(path);
if (parentScript != null) {
if (script is HScript && parentScript is HScript) {
var hscript = cast(script, HScript);
var parentHScript = cast(parentScript, HScript);
if (parentScript != null) {
if (script is HScript && parentScript is HScript) {
var hscript = cast(script, HScript);
var parentHScript = cast(parentScript, HScript);
hscript.interp.variables = parentHScript.interp.variables;
hscript.interp.publicVariables = parentHScript.interp.publicVariables;
hscript.interp.staticVariables = parentHScript.interp.staticVariables;
hscript.interp.variables = parentHScript.interp.variables;
hscript.interp.publicVariables = parentHScript.interp.publicVariables;
hscript.interp.staticVariables = parentHScript.interp.staticVariables;
script.setParent(parentHScript.interp.scriptObject);
}
}
script.setParent(parentHScript.interp.scriptObject);
}
}
script.load();
script.load();
#if ALLOW_MULTITHREADING
thread = Thread.createWithEventLoop(function() {
// Prevent the thread from being auto deleted
Thread.current().events.promise();
});
#end
#if ALLOW_MULTITHREADING
thread = Thread.createWithEventLoop(function() {
// Prevent the thread from being auto deleted
Thread.current().events.promise();
});
#end
__variables = Type.getInstanceFields(Type.getClass(this));
}
__variables = Type.getInstanceFields(Type.getClass(this));
}
public inline function hget(name:String):Dynamic
return __variables.contains(name) ? Reflect.getProperty(this, name) : script.get(name);
public inline function hget(name:String):Dynamic
return __variables.contains(name) ? Reflect.getProperty(this, name) : script.get(name);
public inline function hset(name:String, val:Dynamic):Dynamic {
if (__variables.contains(name))
Reflect.setProperty(this, name, val);
else
script.set(name, val);
return val;
}
public inline function hset(name:String, val:Dynamic):Dynamic {
if (__variables.contains(name))
Reflect.setProperty(this, name, val);
else
script.set(name, val);
return val;
}
public function call(func:String, args:Array<Dynamic>) {
#if ALLOW_MULTITHREADING
thread.events.run(function() {
callEnded = false;
returnValue = script.call(func, args);
callEnded = true;
});
#else
returnValue = script.call(func, args);
callEnded = true;
#end
}
public function call(func:String, args:Array<Dynamic>) {
#if ALLOW_MULTITHREADING
thread.events.run(function() {
callEnded = false;
returnValue = script.call(func, args);
callEnded = true;
});
#else
returnValue = script.call(func, args);
callEnded = true;
#end
}
public function destroy() {
if (script != null) {
script.call("onDestroy");
script.destroy();
}
public function destroy() {
if (script != null) {
script.call("onDestroy");
script.destroy();
}
#if ALLOW_MULTITHREADING
if (thread != null) {
thread.events.runPromised(function() {
// close the thing
});
}
#end
}
#if ALLOW_MULTITHREADING
if (thread != null) {
thread.events.runPromised(function() {
// close the thing
});
}
#end
}
}
+230 -230
View File
@@ -8,266 +8,266 @@ import haxe.io.Path;
* Class used for scripting.
*/
class Script extends FlxBasic implements IFlxDestroyable {
/**
* Use "static var thing = true;" in hscript to use those!!
* are reset every mod switch so once you're done with them make sure to make them null!!
*/
public static var staticVariables:Map<String, Dynamic> = [];
/**
* Use "static var thing = true;" in hscript to use those!!
* are reset every mod switch so once you're done with them make sure to make them null!!
*/
public static var staticVariables:Map<String, Dynamic> = [];
public static function getDefaultVariables(?script:Script):Map<String, Dynamic> {
return [
// Haxe related stuff
"Std" => Std,
"Math" => Math,
"StringTools" => StringTools,
"Json" => haxe.Json,
public static function getDefaultVariables(?script:Script):Map<String, Dynamic> {
return [
// Haxe related stuff
"Std" => Std,
"Math" => Math,
"StringTools" => StringTools,
"Json" => haxe.Json,
// OpenFL & Lime related stuff
"Assets" => openfl.utils.Assets,
"Application" => lime.app.Application,
"window" => lime.app.Application.current.window,
// OpenFL & Lime related stuff
"Assets" => openfl.utils.Assets,
"Application" => lime.app.Application,
"window" => lime.app.Application.current.window,
// Flixel related stuff
"FlxG" => flixel.FlxG,
"FlxSprite" => flixel.FlxSprite,
"FlxBasic" => flixel.FlxBasic,
"FlxCamera" => flixel.FlxCamera,
"state" => flixel.FlxG.state,
"FlxEase" => flixel.tweens.FlxEase,
"FlxTween" => flixel.tweens.FlxTween,
"FlxSound" => flixel.system.FlxSound,
"FlxAssets" => flixel.system.FlxAssets,
"FlxMath" => flixel.math.FlxMath,
"FlxGroup" => flixel.group.FlxGroup,
"FlxTypedGroup" => flixel.group.FlxGroup.FlxTypedGroup,
"FlxSpriteGroup" => flixel.group.FlxSpriteGroup,
"FlxTypeText" => flixel.addons.text.FlxTypeText,
"FlxText" => flixel.text.FlxText,
"FlxTimer" => flixel.util.FlxTimer,
"FlxPoint" => CoolUtil.getMacroAbstractClass("flixel.math.FlxPoint"),
"FlxAxes" => CoolUtil.getMacroAbstractClass("flixel.util.FlxAxes"),
"FlxColor" => CoolUtil.getMacroAbstractClass("flixel.util.FlxColor"),
// Flixel related stuff
"FlxG" => flixel.FlxG,
"FlxSprite" => flixel.FlxSprite,
"FlxBasic" => flixel.FlxBasic,
"FlxCamera" => flixel.FlxCamera,
"state" => flixel.FlxG.state,
"FlxEase" => flixel.tweens.FlxEase,
"FlxTween" => flixel.tweens.FlxTween,
"FlxSound" => flixel.system.FlxSound,
"FlxAssets" => flixel.system.FlxAssets,
"FlxMath" => flixel.math.FlxMath,
"FlxGroup" => flixel.group.FlxGroup,
"FlxTypedGroup" => flixel.group.FlxGroup.FlxTypedGroup,
"FlxSpriteGroup" => flixel.group.FlxSpriteGroup,
"FlxTypeText" => flixel.addons.text.FlxTypeText,
"FlxText" => flixel.text.FlxText,
"FlxTimer" => flixel.util.FlxTimer,
"FlxPoint" => CoolUtil.getMacroAbstractClass("flixel.math.FlxPoint"),
"FlxAxes" => CoolUtil.getMacroAbstractClass("flixel.util.FlxAxes"),
"FlxColor" => CoolUtil.getMacroAbstractClass("flixel.util.FlxColor"),
// Engine related stuff
"engine" => {
// Engine related stuff
"engine" => {
commit: funkin.macros.GitCommitMacro.commitNumber,
build: 2675, // 2675 being the last build num before it was removed
name: "Codename Engine"
},
"ModState" => funkin.scripting.ModState,
"ModSubState" => funkin.scripting.ModSubState,
"PlayState" => funkin.game.PlayState,
"GameOverSubstate" => funkin.game.GameOverSubstate,
"HealthIcon" => funkin.game.HealthIcon,
"HudCamera" => funkin.game.HudCamera,
"Note" => funkin.game.Note,
"Strum" => funkin.game.Strum,
"StrumLine" => funkin.game.StrumLine,
"Character" => funkin.game.Character,
"Boyfriend" => funkin.game.Character, // for compatibility
"PauseSubstate" => funkin.menus.PauseSubState,
"FreeplayState" => funkin.menus.FreeplayState,
"MainMenuState" => funkin.menus.MainMenuState,
"PauseSubState" => funkin.menus.PauseSubState,
"StoryMenuState" => funkin.menus.StoryMenuState,
"TitleState" => funkin.menus.TitleState,
"Options" => funkin.options.Options,
"Paths" => funkin.system.Paths,
"Conductor" => funkin.system.Conductor,
"FunkinShader" => funkin.shaders.FunkinShader,
"CustomShader" => funkin.shaders.CustomShader,
"FunkinText" => funkin.ui.FunkinText,
"Alphabet" => funkin.ui.Alphabet,
build: 2675, // 2675 being the last build num before it was removed
name: "Codename Engine"
},
"ModState" => funkin.scripting.ModState,
"ModSubState" => funkin.scripting.ModSubState,
"PlayState" => funkin.game.PlayState,
"GameOverSubstate" => funkin.game.GameOverSubstate,
"HealthIcon" => funkin.game.HealthIcon,
"HudCamera" => funkin.game.HudCamera,
"Note" => funkin.game.Note,
"Strum" => funkin.game.Strum,
"StrumLine" => funkin.game.StrumLine,
"Character" => funkin.game.Character,
"Boyfriend" => funkin.game.Character, // for compatibility
"PauseSubstate" => funkin.menus.PauseSubState,
"FreeplayState" => funkin.menus.FreeplayState,
"MainMenuState" => funkin.menus.MainMenuState,
"PauseSubState" => funkin.menus.PauseSubState,
"StoryMenuState" => funkin.menus.StoryMenuState,
"TitleState" => funkin.menus.TitleState,
"Options" => funkin.options.Options,
"Paths" => funkin.system.Paths,
"Conductor" => funkin.system.Conductor,
"FunkinShader" => funkin.shaders.FunkinShader,
"CustomShader" => funkin.shaders.CustomShader,
"FunkinText" => funkin.ui.FunkinText,
"Alphabet" => funkin.ui.Alphabet,
"CoolUtil" => funkin.utils.CoolUtil,
"IniUtil" => funkin.utils.IniUtil,
"XMLUtil" => funkin.utils.XMLUtil,
#if sys "ZipUtil" => funkin.utils.ZipUtil, #end
"MarkdownUtil" => funkin.utils.MarkdownUtil,
"EngineUtil" => funkin.utils.EngineUtil,
];
}
public static function getDefaultPreprocessors():Map<String, Dynamic> {
return [
"CODENAME_ENGINE" => true,
"CODENAME_VER" => Application.current.meta.get('version'),
"CODENAME_BUILD" => 2675,
"CODENAME_COMMIT" => funkin.macros.GitCommitMacro.commitNumber,
"desktop" => #if desktop true #else false #end,
"windows" => #if windows true #else false #end,
"hl" => #if hl true #else false #end,
"neko" => #if neko true #else false #end,
"linux" => #if linux true #else false #end,
"mac" => #if mac true #else false #end,
"macos" => #if macos true #else false #end,
"android" => #if android true #else false #end,
"web" => #if web true #else false #end,
"debug" => #if debug true #else false #end,
"release" => #if release true #else false #end,
"final" => #if final true #else false #end,
"MOD_SUPPORT" => #if MOD_SUPPORT true #else false #end,
"GLOBAL_SCRIPT" => #if GLOBAL_SCRIPT true #else false #end,
"SOFTCODED_STATES" => #if SOFTCODED_STATES true #else false #end,
"USE_SOURCE_ASSETS" => #if USE_SOURCE_ASSETS true #else false #end,
"USE_ADAPTED_ASSETS" => #if USE_ADAPTED_ASSETS true #else false #end,
];
}
/**
* All available script extensions
*/
public static var scriptExtensions:Array<String> = [
"hx", "hscript", "hsc", "hxs", "lua" /** ACTUALLY NOT SUPPORTED, ONLY FOR THE MESSAGE **/
];
"CoolUtil" => funkin.utils.CoolUtil,
"IniUtil" => funkin.utils.IniUtil,
"XMLUtil" => funkin.utils.XMLUtil,
#if sys "ZipUtil" => funkin.utils.ZipUtil, #end
"MarkdownUtil" => funkin.utils.MarkdownUtil,
"EngineUtil" => funkin.utils.EngineUtil,
];
}
public static function getDefaultPreprocessors():Map<String, Dynamic> {
return [
"CODENAME_ENGINE" => true,
"CODENAME_VER" => Application.current.meta.get('version'),
"CODENAME_BUILD" => 2675,
"CODENAME_COMMIT" => funkin.macros.GitCommitMacro.commitNumber,
"desktop" => #if desktop true #else false #end,
"windows" => #if windows true #else false #end,
"hl" => #if hl true #else false #end,
"neko" => #if neko true #else false #end,
"linux" => #if linux true #else false #end,
"mac" => #if mac true #else false #end,
"macos" => #if macos true #else false #end,
"android" => #if android true #else false #end,
"web" => #if web true #else false #end,
"debug" => #if debug true #else false #end,
"release" => #if release true #else false #end,
"final" => #if final true #else false #end,
"MOD_SUPPORT" => #if MOD_SUPPORT true #else false #end,
"GLOBAL_SCRIPT" => #if GLOBAL_SCRIPT true #else false #end,
"SOFTCODED_STATES" => #if SOFTCODED_STATES true #else false #end,
"USE_SOURCE_ASSETS" => #if USE_SOURCE_ASSETS true #else false #end,
"USE_ADAPTED_ASSETS" => #if USE_ADAPTED_ASSETS true #else false #end,
];
}
/**
* All available script extensions
*/
public static var scriptExtensions:Array<String> = [
"hx", "hscript", "hsc", "hxs", "lua" /** ACTUALLY NOT SUPPORTED, ONLY FOR THE MESSAGE **/
];
/**
* Currently executing script.
*/
public static var curScript:Script = null;
/**
* Currently executing script.
*/
public static var curScript:Script = null;
/**
* Script name (with extension)
*/
public var fileName:String;
/**
* Script name (with extension)
*/
public var fileName:String;
/**
* Path to the script.
*/
public var path:String = null;
/**
* Path to the script.
*/
public var path:String = null;
/**
* Creates a script from the specified asset path. The language is automatically determined.
* @param path Path in assets
*/
public static function create(path:String):Script {
if (Assets.exists(path)) {
return switch(Path.extension(path).toLowerCase()) {
case "hx" | "hscript" | "hsc" | "hxs":
new HScript(path);
case "lua":
Logs.trace("Lua is not supported in this engine. Use HScript instead.", ERROR);
new DummyScript(path);
default:
new DummyScript(path);
}
}
return new DummyScript(path);
}
/**
* Creates a script from the specified asset path. The language is automatically determined.
* @param path Path in assets
*/
public static function create(path:String):Script {
if (Assets.exists(path)) {
return switch(Path.extension(path).toLowerCase()) {
case "hx" | "hscript" | "hsc" | "hxs":
new HScript(path);
case "lua":
Logs.trace("Lua is not supported in this engine. Use HScript instead.", ERROR);
new DummyScript(path);
default:
new DummyScript(path);
}
}
return new DummyScript(path);
}
/**
* Creates a new instance of the script class.
* @param path
*/
public function new(path:String) {
super();
/**
* Creates a new instance of the script class.
* @param path
*/
public function new(path:String) {
super();
fileName = Path.withoutDirectory(path);
this.path = path;
onCreate(path);
for(k=>e in getDefaultVariables(this)) {
set(k, e);
}
}
fileName = Path.withoutDirectory(path);
this.path = path;
onCreate(path);
for(k=>e in getDefaultVariables(this)) {
set(k, e);
}
}
/**
* Loads the script
*/
public function load() {
var oldScript = curScript;
curScript = this;
onLoad();
curScript = oldScript;
}
/**
* Loads the script
*/
public function load() {
var oldScript = curScript;
curScript = this;
onLoad();
curScript = oldScript;
}
/**
* HSCRIPT ONLY FOR NOW
* Sets the "public" variables map for ScriptPack
*/
public function setPublicMap(map:Map<String, Dynamic>) {
/**
* HSCRIPT ONLY FOR NOW
* Sets the "public" variables map for ScriptPack
*/
public function setPublicMap(map:Map<String, Dynamic>) {
}
}
/**
* Hot-reloads the script, if possible
*/
public function reload() {
/**
* Hot-reloads the script, if possible
*/
public function reload() {
}
}
/**
* Traces something as this script.
*/
public function trace(v:Dynamic) {
Logs.traceColored([
Logs.logText('${fileName}: ', GREEN),
Logs.logText(Std.string(v))
], TRACE);
}
/**
* Traces something as this script.
*/
public function trace(v:Dynamic) {
Logs.traceColored([
Logs.logText('${fileName}: ', GREEN),
Logs.logText(Std.string(v))
], TRACE);
}
/**
* Calls the function `func` defined in the script.
* @param func Name of the function
* @param parameters (Optional) Parameters of the function.
* @return Result (if void, then null)
*/
public function call(func:String, ?parameters:Array<Dynamic>):Dynamic {
var oldScript = curScript;
curScript = this;
/**
* Calls the function `func` defined in the script.
* @param func Name of the function
* @param parameters (Optional) Parameters of the function.
* @return Result (if void, then null)
*/
public function call(func:String, ?parameters:Array<Dynamic>):Dynamic {
var oldScript = curScript;
curScript = this;
var result = onCall(func, parameters == null ? [] : parameters);
var result = onCall(func, parameters == null ? [] : parameters);
curScript = oldScript;
return result;
}
curScript = oldScript;
return result;
}
/**
* Sets a script's parent object so that its properties can be accessed easily. Ex: Passing `PlayState.instance` will allow `boyfriend` to be typed instead of `PlayState.instance.boyfriend`.
* @param variable Parent variable.
*/
public function setParent(variable:Dynamic) {}
/**
* Sets a script's parent object so that its properties can be accessed easily. Ex: Passing `PlayState.instance` will allow `boyfriend` to be typed instead of `PlayState.instance.boyfriend`.
* @param variable Parent variable.
*/
public function setParent(variable:Dynamic) {}
/**
* Gets the variable `variable` from the script's variables.
* @param variable Name of the variable.
* @return Variable (or null if it doesn't exists)
*/
public function get(variable:String):Dynamic {return null;}
/**
* Gets the variable `variable` from the script's variables.
* @param variable Name of the variable.
* @return Variable (or null if it doesn't exists)
*/
public function get(variable:String):Dynamic {return null;}
/**
* Gets the variable `variable` from the script's variables.
* @param variable Name of the variable.
* @return Variable (or null if it doesn't exists)
*/
public function set(variable:String, value:Dynamic):Void {}
/**
* Gets the variable `variable` from the script's variables.
* @param variable Name of the variable.
* @return Variable (or null if it doesn't exists)
*/
public function set(variable:String, value:Dynamic):Void {}
/**
* Shows an error from this script.
* @param text Text of the error (ex: Null Object Reference).
* @param additionalInfo Additional information you could provide.
*/
public function error(text:String, ?additionalInfo:Dynamic):Void {
Logs.traceColored([
Logs.logText(fileName, RED),
Logs.logText(text)
], ERROR);
}
/**
* Shows an error from this script.
* @param text Text of the error (ex: Null Object Reference).
* @param additionalInfo Additional information you could provide.
*/
public function error(text:String, ?additionalInfo:Dynamic):Void {
Logs.traceColored([
Logs.logText(fileName, RED),
Logs.logText(text)
], ERROR);
}
/**
* PRIVATE HANDLERS - DO NOT TOUCH
*/
private function onCall(func:String, parameters:Array<Dynamic>):Dynamic {
return null;
}
public function onCreate(path:String) {}
/**
* PRIVATE HANDLERS - DO NOT TOUCH
*/
private function onCall(func:String, parameters:Array<Dynamic>):Dynamic {
return null;
}
public function onCreate(path:String) {}
public function onLoad() {}
public function onLoad() {}
public function onDestroy() {};
public function onDestroy() {};
public override function destroy() {
super.destroy();
onDestroy();
}
public override function destroy() {
super.destroy();
onDestroy();
}
}
+97 -97
View File
@@ -4,117 +4,117 @@ import funkin.scripting.events.CancellableEvent;
@:access(CancellableEvent)
class ScriptPack extends Script {
public var scripts:Array<Script> = [];
public var additionalDefaultVariables:Map<String, Dynamic> = [];
public var publicVariables:Map<String, Dynamic> = [];
public var parent:Dynamic = null;
public var scripts:Array<Script> = [];
public var additionalDefaultVariables:Map<String, Dynamic> = [];
public var publicVariables:Map<String, Dynamic> = [];
public var parent:Dynamic = null;
public override function load() {
for(e in scripts) {
e.load();
}
}
public override function load() {
for(e in scripts) {
e.load();
}
}
public function contains(path:String) {
for(e in scripts)
if (e.path == path)
return true;
return false;
}
public function new(name:String) {
additionalDefaultVariables["importScript"] = importScript;
super(name);
}
public function contains(path:String) {
for(e in scripts)
if (e.path == path)
return true;
return false;
}
public function new(name:String) {
additionalDefaultVariables["importScript"] = importScript;
super(name);
}
public function getByPath(name:String) {
for(s in scripts)
if (s.path == name)
return s;
return null;
}
public function getByPath(name:String) {
for(s in scripts)
if (s.path == name)
return s;
return null;
}
public function getByName(name:String) {
for(s in scripts)
if (s.fileName == name)
return s;
return null;
}
public function importScript(path:String):Script {
var script = Script.create(Paths.script(path));
if (script is DummyScript) {
throw 'Script at ${path} does not exist.';
return null;
}
add(script);
script.load();
return script;
}
public function getByName(name:String) {
for(s in scripts)
if (s.fileName == name)
return s;
return null;
}
public function importScript(path:String):Script {
var script = Script.create(Paths.script(path));
if (script is DummyScript) {
throw 'Script at ${path} does not exist.';
return null;
}
add(script);
script.load();
return script;
}
public override function call(func:String, ?parameters:Array<Dynamic>):Dynamic {
for(e in scripts)
e.call(func, parameters);
return null;
}
public override function call(func:String, ?parameters:Array<Dynamic>):Dynamic {
for(e in scripts)
e.call(func, parameters);
return null;
}
/**
* Sends an event to every single script, and returns the event.
* @param func Function to call
* @param event Event (will be the first parameter of the function)
* @return (modified by scripts)
*/
public function event<T:CancellableEvent>(func:String, event:T):T {
for(e in scripts) {
e.call(func, [event]);
@:privateAccess
if (event.cancelled && !event.__continueCalls) break;
}
return event;
}
/**
* Sends an event to every single script, and returns the event.
* @param func Function to call
* @param event Event (will be the first parameter of the function)
* @return (modified by scripts)
*/
public function event<T:CancellableEvent>(func:String, event:T):T {
for(e in scripts) {
e.call(func, [event]);
@:privateAccess
if (event.cancelled && !event.__continueCalls) break;
}
return event;
}
public override function get(val:String):Dynamic {
for(e in scripts) {
var v = e.get(val);
if (v != null) return v;
}
return null;
}
public override function get(val:String):Dynamic {
for(e in scripts) {
var v = e.get(val);
if (v != null) return v;
}
return null;
}
public override function reload() {
for(e in scripts) e.reload();
}
public override function reload() {
for(e in scripts) e.reload();
}
public override function set(val:String, value:Dynamic) {
for(e in scripts) e.set(val, value);
}
public override function set(val:String, value:Dynamic) {
for(e in scripts) e.set(val, value);
}
public override function setParent(parent:Dynamic) {
this.parent = parent;
for(e in scripts) e.setParent(parent);
}
public override function setParent(parent:Dynamic) {
this.parent = parent;
for(e in scripts) e.setParent(parent);
}
public override function onDestroy() {
for(e in scripts) e.destroy();
}
public override function onDestroy() {
for(e in scripts) e.destroy();
}
public override function onCreate(path:String) {}
public override function onCreate(path:String) {}
public function add(script:Script) {
scripts.push(script);
__configureNewScript(script);
}
public function add(script:Script) {
scripts.push(script);
__configureNewScript(script);
}
public function remove(script:Script) {
scripts.remove(script);
}
public function remove(script:Script) {
scripts.remove(script);
}
public function insert(pos:Int, script:Script) {
scripts.insert(pos, script);
__configureNewScript(script);
}
public function insert(pos:Int, script:Script) {
scripts.insert(pos, script);
__configureNewScript(script);
}
private function __configureNewScript(script:Script) {
if (parent != null) script.setParent(parent);
script.setPublicMap(publicVariables);
for(k=>e in additionalDefaultVariables) script.set(k, e);
}
private function __configureNewScript(script:Script) {
if (parent != null) script.setParent(parent);
script.setPublicMap(publicVariables);
for(k=>e in additionalDefaultVariables) script.set(k, e);
}
}
+12 -12
View File
@@ -4,18 +4,18 @@ import funkin.game.StrumLine;
import flixel.math.FlxPoint;
class CamMoveEvent extends CancellableEvent {
/**
* Final camera position.
*/
public var position:FlxPoint;
/**
* Final camera position.
*/
public var position:FlxPoint;
/**
* Currently focused strumline.
*/
public var strumLine:StrumLine;
/**
* Currently focused strumline.
*/
public var strumLine:StrumLine;
/**
* Number of focused characters
*/
public var focusedCharacters:Int;
/**
* Number of focused characters
*/
public var focusedCharacters:Int;
}
@@ -5,52 +5,52 @@ import flixel.util.FlxDestroyUtil.IFlxDestroyable;
@:allow(ScriptPack)
@:autoBuild(funkin.macros.EventMacro.build())
class CancellableEvent implements IFlxDestroyable {
@:dox(hide) public var cancelled:Bool = false;
@:dox(hide) private var __continueCalls:Bool = true;
@:dox(hide) public var cancelled:Bool = false;
@:dox(hide) private var __continueCalls:Bool = true;
/**
* Additional data if used in scripts
*/
public var data:Dynamic = {};
/**
* Additional data if used in scripts
*/
public var data:Dynamic = {};
/**
* Prevents default action from occurring.
* @param c Whenever the scripts following this one should be called or not. (Defaults to `true`)
*/
public function preventDefault(c:Bool = false) {
cancelled = true;
__continueCalls = c;
}
/**
* Prevents default action from occurring.
* @param c Whenever the scripts following this one should be called or not. (Defaults to `true`)
*/
public function preventDefault(c:Bool = false) {
cancelled = true;
__continueCalls = c;
}
@:dox(hide)
public function cancel(c:Bool = true) {preventDefault(c);}
@:dox(hide)
public function cancel(c:Bool = true) {preventDefault(c);}
/**
* Creates a new cancellable event.
* This allows scripts to call `cancel()` to cancel the event.
*/
public function new() {}
/**
* Creates a new cancellable event.
* This allows scripts to call `cancel()` to cancel the event.
*/
public function new() {}
public function recycleBase() {
data = {};
cancelled = false;
__continueCalls = true;
}
public function recycleBase() {
data = {};
cancelled = false;
__continueCalls = true;
}
/**
* Returns a string representation of the event, in this format:
* `[CancellableEvent]`
* `[CancellableEvent (Cancelled)]`
* @return String
*/
public function toString():String {
var fields = Reflect.fields(this);
var claName = Type.getClassName(Type.getClass(this)).split(".");
var rep = '[${claName[claName.length-1]}${cancelled ? " (Cancelled)" : ""}]';
return rep;
}
/**
* Returns a string representation of the event, in this format:
* `[CancellableEvent]`
* `[CancellableEvent (Cancelled)]`
* @return String
*/
public function toString():String {
var fields = Reflect.fields(this);
var claName = Type.getClassName(Type.getClass(this)).split(".");
var rep = '[${claName[claName.length-1]}${cancelled ? " (Cancelled)" : ""}]';
return rep;
}
public function destroy() {
data = null;
}
public function destroy() {
data = null;
}
}
@@ -4,42 +4,42 @@ import flixel.tweens.FlxTween;
import flixel.system.FlxSound;
class CountdownEvent extends CancellableEvent {
/**
* At which count the countdown is. Normally goes 0-1-2-3-4 unless `PlayState.instance.introLength` is changed.
*/
public var swagCounter:Int;
/**
* Volume at which the intro countdown sound will play.
*/
public var volume:Float;
/**
* Path of the intro sound that'll be played.
*/
public var soundPath:String;
/**
* Path to the sprite path that'll be shown.
*/
public var spritePath:String;
/**
* Scale of the sprite.
*/
public var scale:Float;
/**
* Whenever antialiasing is enabled or not.
*/
public var antialiasing:Bool;
/**
* At which count the countdown is. Normally goes 0-1-2-3-4 unless `PlayState.instance.introLength` is changed.
*/
public var swagCounter:Int;
/**
* Volume at which the intro countdown sound will play.
*/
public var volume:Float;
/**
* Path of the intro sound that'll be played.
*/
public var soundPath:String;
/**
* Path to the sprite path that'll be shown.
*/
public var spritePath:String;
/**
* Scale of the sprite.
*/
public var scale:Float;
/**
* Whenever antialiasing is enabled or not.
*/
public var antialiasing:Bool;
/**
* Created sprite, only available in `onPostCountdown`
*/
public var sprite:FlxSprite;
/**
* Created tween for the sprite, only available in `onPostCountdown`
*/
public var spriteTween:FlxTween;
/**
* Created sound, only available in `onPostCountdown`
*/
public var sound:FlxSound;
/**
* Created sprite, only available in `onPostCountdown`
*/
public var sprite:FlxSprite;
/**
* Created tween for the sprite, only available in `onPostCountdown`
*/
public var spriteTween:FlxTween;
/**
* Created sound, only available in `onPostCountdown`
*/
public var sound:FlxSound;
}
+1 -1
View File
@@ -1,5 +1,5 @@
package funkin.scripting.events;
class DanceEvent extends CancellableEvent {
public var danced:Bool;
public var danced:Bool;
}
@@ -3,32 +3,32 @@ package funkin.scripting.events;
import funkin.scripting.events.PlayAnimEvent.PlayAnimContext;
class DirectionAnimEvent extends CancellableEvent {
/**
Default animation that will be played
**/
public var animName:String;
/**
In which direction the animation will be played
**/
public var direction:Int;
/**
The suffix of the animation (ex: "-alt") - Defaults to ""
**/
public var suffix:String;
/**
Context of the animation. Is either equal to `SING` or `MISS`.
**/
public var context:PlayAnimContext;
/**
Whenever the animation will play reversed or not.
**/
public var reversed:Bool;
/**
At what frame the animation will start playing
**/
public var frame:Int;
/**
Whenever the animation will play reversed or not.
**/
public var force:Bool = true;
/**
Default animation that will be played
**/
public var animName:String;
/**
In which direction the animation will be played
**/
public var direction:Int;
/**
The suffix of the animation (ex: "-alt") - Defaults to ""
**/
public var suffix:String;
/**
Context of the animation. Is either equal to `SING` or `MISS`.
**/
public var context:PlayAnimContext;
/**
Whenever the animation will play reversed or not.
**/
public var reversed:Bool;
/**
At what frame the animation will start playing
**/
public var frame:Int;
/**
Whenever the animation will play reversed or not.
**/
public var force:Bool = true;
}
@@ -5,8 +5,8 @@ import discord_rpc.DiscordRpc.DiscordPresenceOptions;
#end
class DiscordPresenceUpdateEvent extends CancellableEvent {
/**
* Object containing all of the data for the presence. Can be altered.
*/
public var presenceData:#if DISCORD_RPC DiscordPresenceOptions #else Dynamic #end;
/**
* Object containing all of the data for the presence. Can be altered.
*/
public var presenceData:#if DISCORD_RPC DiscordPresenceOptions #else Dynamic #end;
}
@@ -1,20 +1,20 @@
package funkin.scripting.events;
class FreeplaySongSelectEvent extends CancellableEvent {
/**
* Song name that is about to be played
*/
public var song:String;
/**
* Difficulty name
*/
public var difficulty:String;
/**
* Whenever opponent mode is enabled or not.
*/
public var opponentMode:Bool;
/**
* Whenever coop mode is enabled.
*/
public var coopMode:Bool;
/**
* Song name that is about to be played
*/
public var song:String;
/**
* Difficulty name
*/
public var difficulty:String;
/**
* Whenever opponent mode is enabled or not.
*/
public var opponentMode:Bool;
/**
* Whenever coop mode is enabled.
*/
public var coopMode:Bool;
}
@@ -3,31 +3,31 @@ package funkin.scripting.events;
import funkin.game.StrumLine;
class InputSystemEvent extends CancellableEvent {
/**
* Array containing whenever a specific control is pressed or not.
* For example, `pressed[0]` will return whenever the left strum was pressed.
*/
public var pressed:Array<Bool>;
/**
* Array containing whenever a specific control is pressed or not.
* For example, `pressed[0]` will return whenever the left strum was pressed.
*/
public var pressed:Array<Bool>;
/**
* Array containing whenever a specific control was pressed (not hold) this frame or not.
* For example, `justPressed[0]` will return whenever the left strum was just pressed.
*/
public var justPressed:Array<Bool>;
/**
* Array containing whenever a specific control was pressed (not hold) this frame or not.
* For example, `justPressed[0]` will return whenever the left strum was just pressed.
*/
public var justPressed:Array<Bool>;
/**
* Array containing whenever a specific control was released this frame or not.
* For example, `justReleased[0]` will return whenever the left strum was just released.
*/
public var justReleased:Array<Bool>;
/**
* Array containing whenever a specific control was released this frame or not.
* For example, `justReleased[0]` will return whenever the left strum was just released.
*/
public var justReleased:Array<Bool>;
/**
* Strumline which input is being processed.
*/
public var strumLine:StrumLine;
/**
* Strumline which input is being processed.
*/
public var strumLine:StrumLine;
/**
* ID of the Strumline.
*/
public var strumLineID:Int;
/**
* ID of the Strumline.
*/
public var strumLineID:Int;
}
@@ -1,23 +1,23 @@
package funkin.scripting.events;
class MenuChangeEvent extends CancellableEvent {
/**
* Value before the change
*/
public var oldValue:Int;
/**
* Value before the change
*/
public var oldValue:Int;
/**
* Value after the change
*/
public var value:Int;
/**
* Value after the change
*/
public var value:Int;
/**
* Amount of change
*/
public var change:Int;
/**
* Amount of change
*/
public var change:Int;
/**
* Whenever the menu SFX should be played.
*/
public var playMenuSFX:Bool = true;
/**
* Whenever the menu SFX should be played.
*/
public var playMenuSFX:Bool = true;
}
+4 -4
View File
@@ -1,8 +1,8 @@
package funkin.scripting.events;
class NameEvent extends CancellableEvent {
/**
* Name
*/
public var name:String;
/**
* Name
*/
public var name:String;
}
@@ -3,48 +3,48 @@ package funkin.scripting.events;
import funkin.game.Note;
class NoteCreationEvent extends CancellableEvent {
/**
* Note that is being created
*/
public var note:Note;
/**
* Note that is being created
*/
public var note:Note;
/**
* ID of the strum (from 0 to 3)
*/
public var strumID:Int;
/**
* ID of the strum (from 0 to 3)
*/
public var strumID:Int;
/**
* Note Type (ex: "My Super Cool Note", or "Mine")
*/
public var noteType:String;
/**
* Note Type (ex: "My Super Cool Note", or "Mine")
*/
public var noteType:String;
/**
* ID of the note type.
*/
public var noteTypeID:Int;
/**
* ID of the note type.
*/
public var noteTypeID:Int;
/**
* ID of the player.
*/
public var strumLineID:Int;
/**
* ID of the player.
*/
public var strumLineID:Int;
/**
* Whenever the note will need to be hit by the player
*/
public var mustHit:Bool;
/**
* Whenever the note will need to be hit by the player
*/
public var mustHit:Bool;
/**
* Note sprite, if you only want to replace the sprite.
*/
public var noteSprite:String;
/**
* Note sprite, if you only want to replace the sprite.
*/
public var noteSprite:String;
/**
* Note scale, if you only want to replace the scale.
*/
public var noteScale:Float;
/**
* Note scale, if you only want to replace the scale.
*/
public var noteScale:Float;
/**
* Sing animation suffix. "-alt" for alt anim or "" for normal notes.
*/
public var animSuffix:String;
/**
* Sing animation suffix. "-alt" for alt anim or "" for normal notes.
*/
public var animSuffix:String;
}
+156 -156
View File
@@ -4,170 +4,170 @@ import funkin.game.Note;
import funkin.game.Character;
class NoteHitEvent extends CancellableEvent {
@:dox(hide) public var animCancelled:Bool = false;
@:dox(hide) public var strumGlowCancelled:Bool = false;
@:dox(hide) public var deleteNote:Bool = true;
@:dox(hide) public var unmuteVocals:Bool = true;
@:dox(hide) public var enableCamZooming:Bool = true;
@:dox(hide) public var autoHitLastSustain:Bool = true;
@:dox(hide) public var animCancelled:Bool = false;
@:dox(hide) public var strumGlowCancelled:Bool = false;
@:dox(hide) public var deleteNote:Bool = true;
@:dox(hide) public var unmuteVocals:Bool = true;
@:dox(hide) public var enableCamZooming:Bool = true;
@:dox(hide) public var autoHitLastSustain:Bool = true;
/**
* Whenever a miss should be added.
*/
public var misses:Bool = true;
/**
* Whenever a miss should be added.
*/
public var countAsCombo:Bool = true;
/**
* Whenever ratings should be shown or not.
*/
public var showRating:Null<Bool> = null;
/**
* Note that has been pressed
*/
public var note:Note;
/**
* Character that pressed the note.
*/
public var character(get, set):Character;
/**
* Characters that pressed the note.
*/
public var characters:Array<Character>;
/**
* Whenever the Character is a player
*/
public var player:Bool;
/**
* Note Type name (null if default note)
*/
public var noteType:String;
/**
* Suffix of the animation. "-alt" for alt notes, "" for normal ones.
*/
public var animSuffix:String;
/**
* Prefix of the rating sprite path. Defaults to "game/score/"
*/
public var ratingPrefix:String;
/**
* Suffix of the rating sprite path.
*/
public var ratingSuffix:String;
/**
* Direction of the press (0 = Left, 1 = Down, 2 = Up, 3 = Right)
*/
public var direction:Int;
/**
* Score gained after note press.
*/
public var score:Int;
/**
* Accuracy gained from pressing this note. From 0 to 1. null means no accuracy is gained.
*/
public var accuracy:Null<Float>;
/**
* The amount of health that'll be gained from pressing that note. If called from `onPlayerMiss`, the value will be negative.
*/
public var healthGain:Float;
/**
* Rating name. Defaults to "sick", "good", "bad" and "shit". Customisable.
*/
public var rating:String = "sick";
/**
* Whenever a splash should be shown when the note is hit.
*/
public var showSplash:Bool = false;
/**
* Scale of combo numbers.
*/
public var numScale:Float = 0.5;
/**
* Whenever antialiasing should be enabled on combo number.
*/
public var numAntialiasing:Bool = true;
/**
* Scale of ratings.
*/
public var ratingScale:Float = 0.7;
/**
* Whenever antialiasing should be enabled on ratings.
*/
public var ratingAntialiasing:Bool = true;
/**
* Whenever the animation should be forced to play.
*/
public var forceAnim:Bool = true;
/**
* Whenever a miss should be added.
*/
public var misses:Bool = true;
/**
* Whenever a miss should be added.
*/
public var countAsCombo:Bool = true;
/**
* Whenever ratings should be shown or not.
*/
public var showRating:Null<Bool> = null;
/**
* Note that has been pressed
*/
public var note:Note;
/**
* Character that pressed the note.
*/
public var character(get, set):Character;
/**
* Characters that pressed the note.
*/
public var characters:Array<Character>;
/**
* Whenever the Character is a player
*/
public var player:Bool;
/**
* Note Type name (null if default note)
*/
public var noteType:String;
/**
* Suffix of the animation. "-alt" for alt notes, "" for normal ones.
*/
public var animSuffix:String;
/**
* Prefix of the rating sprite path. Defaults to "game/score/"
*/
public var ratingPrefix:String;
/**
* Suffix of the rating sprite path.
*/
public var ratingSuffix:String;
/**
* Direction of the press (0 = Left, 1 = Down, 2 = Up, 3 = Right)
*/
public var direction:Int;
/**
* Score gained after note press.
*/
public var score:Int;
/**
* Accuracy gained from pressing this note. From 0 to 1. null means no accuracy is gained.
*/
public var accuracy:Null<Float>;
/**
* The amount of health that'll be gained from pressing that note. If called from `onPlayerMiss`, the value will be negative.
*/
public var healthGain:Float;
/**
* Rating name. Defaults to "sick", "good", "bad" and "shit". Customisable.
*/
public var rating:String = "sick";
/**
* Whenever a splash should be shown when the note is hit.
*/
public var showSplash:Bool = false;
/**
* Scale of combo numbers.
*/
public var numScale:Float = 0.5;
/**
* Whenever antialiasing should be enabled on combo number.
*/
public var numAntialiasing:Bool = true;
/**
* Scale of ratings.
*/
public var ratingScale:Float = 0.7;
/**
* Whenever antialiasing should be enabled on ratings.
*/
public var ratingAntialiasing:Bool = true;
/**
* Whenever the animation should be forced to play.
*/
public var forceAnim:Bool = true;
/**
* Prevents the default sing animation from being played.
*/
public function preventAnim() {
animCancelled = true;
}
/**
* Prevents the default sing animation from being played.
*/
public function preventAnim() {
animCancelled = true;
}
@:dox(hide)
public function cancelAnim() {preventAnim();}
@:dox(hide)
public function cancelAnim() {preventAnim();}
/**
* Prevents the note from being deleted.
*/
public function preventDeletion() {
deleteNote = false;
}
@:dox(hide)
public function cancelDeletion() {preventDeletion();}
/**
* Prevents the note from being deleted.
*/
public function preventDeletion() {
deleteNote = false;
}
@:dox(hide)
public function cancelDeletion() {preventDeletion();}
/**
* Prevents the vocals volume from being set to 1 after pressing the note.
*/
public function preventVocalsUnmute() {
unmuteVocals = false;
}
@:dox(hide)
public function cancelVocalsUnmute() {preventVocalsUnmute();}
/**
* Prevents the vocals volume from being set to 1 after pressing the note.
*/
public function preventVocalsUnmute() {
unmuteVocals = false;
}
@:dox(hide)
public function cancelVocalsUnmute() {preventVocalsUnmute();}
/**
* Prevents the vocals volume from being muted in case its a parameter of `onPlayerMiss`
*/
public function preventVocalsMute() {
unmuteVocals = true;
}
@:dox(hide)
public function cancelVocalsMute() {preventVocalsMute();}
/**
* Prevents the vocals volume from being muted in case its a parameter of `onPlayerMiss`
*/
public function preventVocalsMute() {
unmuteVocals = true;
}
@:dox(hide)
public function cancelVocalsMute() {preventVocalsMute();}
/**
* Prevents the camera zoom every 4 beats from enabling.
*/
public function preventCamZooming() {
enableCamZooming = false;
}
@:dox(hide)
public function cancelCamZooming() {preventCamZooming();}
/**
* Prevents the camera zoom every 4 beats from enabling.
*/
public function preventCamZooming() {
enableCamZooming = false;
}
@:dox(hide)
public function cancelCamZooming() {preventCamZooming();}
/**
* Prevents the sustain tail (the last one) from being automatically hit when the sustain before it is hit.
*/
public function preventLastSustainHit() {
autoHitLastSustain = false;
}
@:dox(hide)
public function cancelLastSustainHit() {preventLastSustainHit();}
/**
* Prevents the sustain tail (the last one) from being automatically hit when the sustain before it is hit.
*/
public function preventLastSustainHit() {
autoHitLastSustain = false;
}
@:dox(hide)
public function cancelLastSustainHit() {preventLastSustainHit();}
/**
* Prevents the strum from glowing after this note has been pressed.
*/
public function preventStrumGlow() {
strumGlowCancelled = true;
}
@:dox(hide)
public function cancelStrumGlow() {preventStrumGlow();}
/**
* Prevents the strum from glowing after this note has been pressed.
*/
public function preventStrumGlow() {
strumGlowCancelled = true;
}
@:dox(hide)
public function cancelStrumGlow() {preventStrumGlow();}
private inline function get_character()
return characters[0];
private function set_character(char:Character) {
characters = [char];
return char;
}
private inline function get_character()
return characters[0];
private function set_character(char:Character) {
characters = [char];
return char;
}
}
@@ -4,45 +4,45 @@ import funkin.game.Note;
import funkin.game.Strum;
class NoteUpdateEvent extends CancellableEvent {
@:dox(hide) public var __updateHitWindow = true;
@:dox(hide) public var __autoCPUHit = true;
@:dox(hide) public var __reposNote = true;
/**
* Note that is being updated
*/
public var note:Note;
@:dox(hide) public var __updateHitWindow = true;
@:dox(hide) public var __autoCPUHit = true;
@:dox(hide) public var __reposNote = true;
/**
* Note that is being updated
*/
public var note:Note;
/**
* Time elapsed since last frame
*/
public var elapsed:Null<Float>;
/**
* Time elapsed since last frame
*/
public var elapsed:Null<Float>;
/**
* Note's strum (can be changed)
*/
public var strum:Strum;
/**
* Note's strum (can be changed)
*/
public var strum:Strum;
/**
* Cancels the hit window update.
*/
public function cancelWindowUpdate() {
__updateHitWindow = false;
}
@:dox(hide) public function preventWindowUpdate() { cancelWindowUpdate(); }
/**
* Cancels the hit window update.
*/
public function cancelWindowUpdate() {
__updateHitWindow = false;
}
@:dox(hide) public function preventWindowUpdate() { cancelWindowUpdate(); }
/**
* Cancels the automatic CPU hit.
*/
public function cancelAutoCPUHit() {
__autoCPUHit = false;
}
@:dox(hide) public function preventAutoCPUHit() { cancelAutoCPUHit(); }
/**
* Cancels the automatic CPU hit.
*/
public function cancelAutoCPUHit() {
__autoCPUHit = false;
}
@:dox(hide) public function preventAutoCPUHit() { cancelAutoCPUHit(); }
/**
* Cancels the note position update (note will freeze).
*/
public function cancelPositionUpdate() {
__reposNote = false;
}
@:dox(hide) public function preventPositionUpdate() { cancelPositionUpdate(); }
/**
* Cancels the note position update (note will freeze).
*/
public function cancelPositionUpdate() {
__reposNote = false;
}
@:dox(hide) public function preventPositionUpdate() { cancelPositionUpdate(); }
}
@@ -4,13 +4,13 @@ package funkin.scripting.events;
* CANCEL this event to prevent default behaviour!
*/
class PauseCreationEvent extends CancellableEvent {
/**
* Music that is going to be played
*/
public var music:String;
/**
* Music that is going to be played
*/
public var music:String;
/**
* All option names
*/
public var options:Array<String>;
/**
* All option names
*/
public var options:Array<String>;
}
+46 -46
View File
@@ -1,64 +1,64 @@
package funkin.scripting.events;
class PlayAnimEvent extends CancellableEvent {
/**
Name of the animation that's going to be played.
**/
public var animName:String;
/**
Name of the animation that's going to be played.
**/
public var animName:String;
/**
Whenever the animation will be forced or not.
**/
public var force:Bool;
/**
Whenever the animation will be forced or not.
**/
public var force:Bool;
/**
Whenever the animation will play in reverse or not
**/
public var reverse:Bool;
/**
Whenever the animation will play in reverse or not
**/
public var reverse:Bool;
/**
The frame at which the animation will start playing
**/
public var startingFrame:Int = 0;
/**
The frame at which the animation will start playing
**/
public var startingFrame:Int = 0;
/**
Context of the animation
**/
public var context:PlayAnimContext;
/**
Context of the animation
**/
public var context:PlayAnimContext;
}
/**
Contains all contexts possible for `PlayAnimEvent`.
Contains all contexts possible for `PlayAnimEvent`.
**/
@:enum
abstract PlayAnimContext(String) {
/**
No context was given for the animation.
The character won't dance until the animation is finished
**/
var NONE = null;
/**
No context was given for the animation.
The character won't dance until the animation is finished
**/
var NONE = null;
/**
Whenever a note is hit and a sing animation will be played.
The character will only dance after their holdTime is reached.
**/
var SING = "SING";
/**
Whenever a note is hit and a sing animation will be played.
The character will only dance after their holdTime is reached.
**/
var SING = "SING";
/**
Whenever a dance animation is played.
The character's dancing wont be blocked.
**/
var DANCE = "DANCE";
/**
Whenever a dance animation is played.
The character's dancing wont be blocked.
**/
var DANCE = "DANCE";
/**
Whenever a note is missed and a miss animation will be played.
Only for scripting, since it has the same effects as SING.
**/
var MISS = "MISS";
/**
Whenever a note is missed and a miss animation will be played.
Only for scripting, since it has the same effects as SING.
**/
var MISS = "MISS";
/**
Locks the character's animation.
Prevents the character from dancing, even if the animation ended.
**/
var LOCK = "LOCK";
/**
Locks the character's animation.
Prevents the character from dancing, even if the animation ended.
**/
var LOCK = "LOCK";
}
+8 -8
View File
@@ -1,12 +1,12 @@
package funkin.scripting.events;
class PointEvent extends CancellableEvent {
/**
X position
**/
public var x:Float;
/**
Y position
**/
public var y:Float;
/**
X position
**/
public var x:Float;
/**
Y position
**/
public var y:Float;
}
@@ -1,13 +1,13 @@
package funkin.scripting.events;
class RatingUpdateEvent extends CancellableEvent {
/**
New combo
**/
public var rating:ComboRating;
/**
Old combo (may be null)
**/
public var oldRating:ComboRating;
/**
New combo
**/
public var rating:ComboRating;
/**
Old combo (may be null)
**/
public var oldRating:ComboRating;
}
+16 -16
View File
@@ -1,22 +1,22 @@
package funkin.scripting.events;
class ResizeEvent extends CancellableEvent {
/**
* New width
*/
public var width:Int;
/**
* New height
*/
public var height:Int;
/**
* New width
*/
public var width:Int;
/**
* New height
*/
public var height:Int;
/**
* Old width (may be null)
*/
public var oldWidth:Null<Int>;
/**
* Old width (may be null)
*/
public var oldWidth:Null<Int>;
/**
* Old height (may be null)
*/
public var oldHeight:Null<Int>;
/**
* Old height (may be null)
*/
public var oldHeight:Null<Int>;
}
@@ -3,8 +3,8 @@ package funkin.scripting.events;
import funkin.game.Note;
class SimpleNoteEvent extends CancellableEvent {
/**
Note that is affected.
**/
public var note:Note;
/**
Note that is affected.
**/
public var note:Note;
}

Some files were not shown because too many files have changed in this diff Show More