FUCK SPACES!!!! TABS RULES!!! 💪💪💪💪
This commit is contained in:
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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]);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {}
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
@@ -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)}';
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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,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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>;
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user