removed desktop (new ui framework)
|
Before Width: | Height: | Size: 171 B |
|
Before Width: | Height: | Size: 173 B |
@@ -1,36 +0,0 @@
|
||||
<theme folder="desktop/ui/">
|
||||
<!-- WINDOW!! !-->
|
||||
<captionActive path="caption" textColor="#FFFFFF" left="5" top="30" right="5" bottom="5" textSize="16" />
|
||||
<captionInactive path="captionInactive" textColor="#AAFFFFFF" left="5" top="30" right="5" bottom="5" />
|
||||
<captionButtons path="captionButtons" size="21,21" margin="2,0" offset="4,6" />
|
||||
<window color="255,255,255" textColor="0,0,0" font="file://C:/Windows/fonts/tahoma.ttf" fontSize="11"/>
|
||||
|
||||
<!-- BUTTONS !-->
|
||||
<normalButton path="button" textColor="0,0,0" left="4" top="4" right="4" bottom="4" />
|
||||
<hoverButton path="buttonHover" textColor="0,0,0" left="4" top="4" right="4" bottom="4" />
|
||||
<pressedButton path="buttonPressed" textColor="0,0,0" left="4" top="4" right="4" bottom="4" />
|
||||
<disabledButton path="buttonDisabled" textColor="128,128,128" left="4" top="4" right="4" bottom="4" />
|
||||
|
||||
<!-- CHECKBOX -->
|
||||
<checkbox path="checkbox" width="16" height="16"/>
|
||||
|
||||
<!-- TABS -->
|
||||
<tabBackground path="tabBody" textColor="0,0,0" left="4" top="0" right="4" bottom="4" />
|
||||
<tabButtonSelected path="tab" textColor="255,255,255" left="4" top="4" right="4" bottom="0" />
|
||||
<tabButtonUnselected path="tabNonSelected" textColor="0,0,0" left="4" top="6" right="4" bottom="4" />
|
||||
<tabButtonHover path="tabHover" textColor="0,0,0" left="4" top="4" right="4" bottom="4" />
|
||||
<tabButtonPressed path="tabPressed" textColor="0,0,0" left="4" top="4" right="4" bottom="4" />
|
||||
|
||||
<!-- CONTEXT MENU -->
|
||||
<contextBackground path="context" textColor="0,0,0" left="4" top="4" right="4" bottom="4" />
|
||||
<contextOption path="contextOption" textColor="255,255,255" height="20" />
|
||||
|
||||
<!-- MENU BAR -->
|
||||
<menuBar path="menuBar" height="20" />
|
||||
|
||||
<!-- TEXTBOX -->
|
||||
<textbox path="textbox" textColor="0,0,0" left="4" top="4" right="4" bottom="4" />
|
||||
<textboxHover path="textboxHover" textColor="0,0,0" left="4" top="4" right="4" bottom="4" />
|
||||
<textboxPressed path="textboxPressed" textColor="0,0,0" left="4" top="4" right="4" bottom="4" />
|
||||
<textboxFocused path="textboxFocus" textColor="0,0,0" left="4" top="4" right="4" bottom="4" />
|
||||
</theme>
|
||||
|
Before Width: | Height: | Size: 161 B |
|
Before Width: | Height: | Size: 264 B |
|
Before Width: | Height: | Size: 244 B |
|
Before Width: | Height: | Size: 488 B |
|
Before Width: | Height: | Size: 481 B |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 494 B |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 162 B |
|
Before Width: | Height: | Size: 308 B |
|
Before Width: | Height: | Size: 116 B |
|
Before Width: | Height: | Size: 152 B |
|
Before Width: | Height: | Size: 141 B |
|
Before Width: | Height: | Size: 233 B |
|
Before Width: | Height: | Size: 160 B |
|
Before Width: | Height: | Size: 439 B |
|
Before Width: | Height: | Size: 151 B |
|
Before Width: | Height: | Size: 234 B |
|
Before Width: | Height: | Size: 258 B |
|
Before Width: | Height: | Size: 251 B |
|
Before Width: | Height: | Size: 253 B |
|
After Width: | Height: | Size: 1.6 KiB |
@@ -1 +1 @@
|
||||
2492
|
||||
2495
|
||||
@@ -1,222 +0,0 @@
|
||||
package funkin.desktop;
|
||||
|
||||
import flixel.math.FlxRect;
|
||||
import openfl.geom.Rectangle;
|
||||
import lime.app.Application;
|
||||
import openfl.display.BitmapData;
|
||||
import flixel.system.scaleModes.BaseScaleMode;
|
||||
import flixel.system.scaleModes.FixedScaleAdjustSizeScaleMode;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.util.FlxDestroyUtil;
|
||||
import funkin.desktop.editors.*;
|
||||
import funkin.desktop.windows.*;
|
||||
import funkin.desktop.theme.Theme;
|
||||
|
||||
class DesktopMain extends MusicBeatState {
|
||||
public var oldScaleMode:BaseScaleMode;
|
||||
public var wallpaper:FlxSprite;
|
||||
public var screenSize:FlxPoint;
|
||||
|
||||
public var windows:WindowGroup<Window>;
|
||||
|
||||
public static var instance:DesktopMain;
|
||||
|
||||
public static var currentFocus:IDesktopFocusableObject;
|
||||
|
||||
public static var mouseInput:MouseInput;
|
||||
|
||||
public static var theme:Theme = null;
|
||||
|
||||
public static var contextMenu:ContextMenu = null;
|
||||
|
||||
public static function init() {
|
||||
theme = Theme.loadFromAssets(Paths.getPath('images/desktop/ui.xml', TEXT, null));
|
||||
mouseInput = new MouseInput();
|
||||
|
||||
FlxG.signals.preUpdate.add(function() {
|
||||
updateMouseInput();
|
||||
});
|
||||
}
|
||||
|
||||
public override function create() {
|
||||
super.create();
|
||||
|
||||
instance = this;
|
||||
|
||||
FlxG.mouse.useSystemCursor = FlxG.mouse.visible = true;
|
||||
oldScaleMode = FlxG.scaleMode;
|
||||
FlxG.scaleMode = new FixedScaleAdjustSizeScaleMode(false, false);
|
||||
|
||||
wallpaper = new FlxSprite();
|
||||
#if windows
|
||||
try {
|
||||
wallpaper.loadGraphic(BitmapData.fromFile('${Sys.getEnv("AppData")}\\Microsoft\\Windows\\Themes\\TranscodedWallpaper'));
|
||||
} catch(e) #end wallpaper.loadGraphic(Paths.image("menus/menuBG"));
|
||||
wallpaper.scrollFactor.set(0, 0); // anchor at top left
|
||||
wallpaper.antialiasing = true;
|
||||
add(wallpaper);
|
||||
|
||||
screenSize = new FlxPoint(-1, -1);
|
||||
|
||||
windows = new WindowGroup<Window>();
|
||||
add(windows);
|
||||
}
|
||||
|
||||
private static function updateMouseInput() {
|
||||
mouseInput.set(FlxG.mouse.pressed, FlxG.mouse.justPressed, FlxG.mouse.justReleased, FlxG.mouse.pressedRight, FlxG.mouse.justPressedRight, FlxG.mouse.justReleasedRight);
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
updateMouseInput();
|
||||
|
||||
if (contextMenu != null)
|
||||
contextMenu.update(elapsed);
|
||||
|
||||
super.update(elapsed);
|
||||
|
||||
|
||||
if (screenSize.x != FlxG.width || screenSize.y != FlxG.height) {
|
||||
screenSize.set(FlxG.width, FlxG.height);
|
||||
updateScreenRes();
|
||||
}
|
||||
|
||||
// debug window
|
||||
if (FlxG.keys.justPressed.SPACE)
|
||||
windows.add(new Window(new HelloWorld()));
|
||||
if (FlxG.keys.justPressed.F1)
|
||||
windows.add(new Window(new CharacterEditor('dad')));
|
||||
if (FlxG.keys.justPressed.F2)
|
||||
windows.add(new Window(new EditorPlayState()));
|
||||
|
||||
FlxG.sound.enableVolumeChanges = !(currentFocus is IDesktopInputObject);
|
||||
|
||||
// TEMPORARY ESCAPE KEY UNTIL TASKBAR IS ADDED
|
||||
if (FlxG.keys.justPressed.ESCAPE) FlxG.switchState(new funkin.menus.MainMenuState());
|
||||
}
|
||||
|
||||
public function openWindow(content:WindowContent) {
|
||||
return windows.add(new Window(content));
|
||||
}
|
||||
|
||||
public override function draw() {
|
||||
super.draw();
|
||||
if (contextMenu != null)
|
||||
contextMenu.draw();
|
||||
}
|
||||
|
||||
public function updateScreenRes() {
|
||||
// update wallpaper
|
||||
wallpaper.setUnstretchedGraphicSize(FlxG.width, FlxG.height);
|
||||
for(e in windows) {
|
||||
e.onDesktopSizeChange(FlxG.width, FlxG.height);
|
||||
}
|
||||
}
|
||||
|
||||
public override function destroy() {
|
||||
super.destroy();
|
||||
|
||||
FlxG.sound.enableVolumeChanges = true;
|
||||
contextMenu = FlxDestroyUtil.destroy(contextMenu);
|
||||
|
||||
FlxG.scaleMode = oldScaleMode;
|
||||
FlxG.mouse.useSystemCursor = FlxG.mouse.visible = false;
|
||||
|
||||
// TODO: switch back while using config
|
||||
FlxG.resizeGame(1280, 720);
|
||||
|
||||
if (screenSize != null)
|
||||
screenSize.put();
|
||||
}
|
||||
|
||||
public function focusWindow(window:Window) {
|
||||
windows.remove(window, true);
|
||||
windows.add(window);
|
||||
layerCameras();
|
||||
}
|
||||
|
||||
public function layerCameras() {
|
||||
for(win in windows.members) {
|
||||
FlxG.cameras.remove(win.windowCaptionCamera, false);
|
||||
for(e in win.windowCameras) FlxG.cameras.remove(e.camera, false);
|
||||
}
|
||||
for(win in windows.members) {
|
||||
FlxG.cameras.add(win.windowCaptionCamera, false);
|
||||
for(e in win.windowCameras) FlxG.cameras.add(e.camera, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static function loseFocus(obj:IDesktopFocusableObject) {
|
||||
if (currentFocus == obj) {
|
||||
currentFocus.onFocusLost();
|
||||
currentFocus = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static function setFocus(obj:IDesktopFocusableObject) {
|
||||
if (currentFocus == obj) return;
|
||||
if (currentFocus != null)
|
||||
currentFocus.onFocusLost();
|
||||
(currentFocus = obj).onFocus();
|
||||
}
|
||||
|
||||
public static function hasFocus(obj:IDesktopFocusableObject) {
|
||||
return currentFocus == obj;
|
||||
}
|
||||
}
|
||||
|
||||
class MouseInput {
|
||||
public var pressed:Bool = false;
|
||||
public var justPressed:Bool = false;
|
||||
public var justReleased:Bool = false;
|
||||
public var pressedRight:Bool = false;
|
||||
public var justPressedRight:Bool = false;
|
||||
public var justReleasedRight:Bool = false;
|
||||
public var screenPos:FlxPoint = null;
|
||||
private var __cancelled:Bool = false;
|
||||
|
||||
public function cancel() {
|
||||
pressed = justPressed = justReleased = pressedRight = justPressedRight = justReleasedRight = false;
|
||||
__cancelled = true;
|
||||
}
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function set(pressed:Bool, justPressed:Bool, justReleased:Bool, pressedRight:Bool, justPressedRight:Bool, justReleasedRight:Bool) {
|
||||
this.pressed = pressed;
|
||||
this.justPressed = justPressed;
|
||||
this.justReleased = justReleased;
|
||||
this.pressedRight = pressedRight;
|
||||
this.justPressedRight = justPressedRight;
|
||||
this.justReleasedRight = justReleasedRight;
|
||||
this.screenPos = FlxG.mouse.getScreenPosition(FlxG.camera);
|
||||
this.__cancelled = false;
|
||||
}
|
||||
|
||||
public function overlaps(spr:FlxObject, ?camera:FlxCamera) {
|
||||
return overlapsRect(spr, new FlxRect(spr.x, spr.y, spr.width, spr.height), camera);
|
||||
// return FlxG.mouse.overlaps(spr, camera);
|
||||
}
|
||||
|
||||
public function overlapsRect(spr:FlxBasic, rect:FlxRect, ?camera:FlxCamera) {
|
||||
if (__cancelled) return false;
|
||||
if (camera == null) camera = FlxG.camera;
|
||||
if (spr is FlxObject && camera != null) {
|
||||
var obj = cast(spr, FlxObject);
|
||||
rect.x -= camera.scroll.x * obj.scrollFactor.x;
|
||||
rect.y -= camera.scroll.y * obj.scrollFactor.y;
|
||||
}
|
||||
var pos = FlxG.mouse.getScreenPosition(camera);
|
||||
|
||||
return ((pos.x > rect.x) && (pos.x < rect.x + rect.width)) && ((pos.y > rect.y) && (pos.y < rect.y + rect.height));
|
||||
}
|
||||
}
|
||||
|
||||
interface IDesktopFocusableObject {
|
||||
public function onFocus():Void;
|
||||
public function onFocusLost():Void;
|
||||
}
|
||||
|
||||
// useless, only here for
|
||||
interface IDesktopInputObject {
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package funkin.desktop;
|
||||
|
||||
import flixel.util.FlxDestroyUtil.IFlxDestroyable;
|
||||
import openfl.events.Event;
|
||||
import lime.app.Application;
|
||||
import lime.ui.Window;
|
||||
|
||||
class DesktopScreen implements IFlxDestroyable {
|
||||
public var cameras:Array<FlxCamera> = [];
|
||||
public var window:Window;
|
||||
|
||||
public function new() {
|
||||
window = Application.current.createWindow({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: FlxG.width,
|
||||
height: FlxG.height
|
||||
});
|
||||
@:privateAccess
|
||||
Application.current.__addWindow(window);
|
||||
|
||||
window.stage.addEventListener(Event.ENTER_FRAME, onFrameEnter);
|
||||
|
||||
FlxG.signals.preDraw.add(__onPreDraw);
|
||||
FlxG.signals.postDraw.add(__onPostDraw);
|
||||
|
||||
window.onClose.add(destroy);
|
||||
}
|
||||
|
||||
public function addCamera(cam:FlxCamera) {
|
||||
cameras.push(cam);
|
||||
window.stage.addChild(cam.flashSprite);
|
||||
}
|
||||
|
||||
private inline function __onPreDraw() {}
|
||||
private inline function __onPostDraw() {}
|
||||
|
||||
private function onFrameEnter(event:Event) {
|
||||
try {
|
||||
@:privateAccess
|
||||
for(c in cameras)
|
||||
c.render();
|
||||
} catch(e) {
|
||||
trace(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy() {
|
||||
for(c in cameras)
|
||||
c.destroy();
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package funkin.desktop;
|
||||
|
||||
|
||||
class DesktopUtils {
|
||||
public static inline function copyProperties(spr1:FlxObject, spr2:FlxObject) {
|
||||
spr1.cameras = spr2.cameras;
|
||||
spr1.setPosition(spr2.x, spr2.y);
|
||||
spr1.scrollFactor.set(spr2.scrollFactor.x, spr2.scrollFactor.y);
|
||||
}
|
||||
}
|
||||
@@ -1,341 +0,0 @@
|
||||
package funkin.desktop.editors;
|
||||
|
||||
import funkin.game.Character;
|
||||
|
||||
using funkin.utils.XMLUtil;
|
||||
|
||||
class CharacterEditor extends WindowContent {
|
||||
public function new(curCharacter:String) {
|
||||
super('Character Editor - Loading...', 0, 0, 1200, 600);
|
||||
}
|
||||
|
||||
public var camHUD:FlxCamera;
|
||||
public var char:Character;
|
||||
public var curCharacter:String;
|
||||
public var camFollow:FlxObject;
|
||||
public var tabView:TabView;
|
||||
|
||||
public var animList:Array<AnimData> = [];
|
||||
public var animListNames:Array<String> = [];
|
||||
|
||||
public var curAnim:AnimData;
|
||||
|
||||
public var menuBar:MenuBar;
|
||||
|
||||
/**
|
||||
* SILHOUETTES
|
||||
*/
|
||||
public var silhouetteDad:Character;
|
||||
public var silhouetteGf:Character;
|
||||
public var silhouetteBf:Character;
|
||||
|
||||
/**
|
||||
* ANIMATION TAB
|
||||
*/
|
||||
public var animsDropDown:DropDown;
|
||||
public var animNameInput:InputBox;
|
||||
public var animPrefixInput:InputBox;
|
||||
public var animLoopCheckbox:Checkbox;
|
||||
public var animFpsStepper:NumericStepper;
|
||||
public var animOffsetX:NumericStepper;
|
||||
public var animOffsetY:NumericStepper;
|
||||
|
||||
/**
|
||||
* CHARACTER SETTINGS TAB
|
||||
*/
|
||||
public var charSpriteInput:InputBox;
|
||||
public var charIconInput:InputBox;
|
||||
public var charIsPlayerCheckbox:Checkbox;
|
||||
public var charIsGFCheckbox:Checkbox;
|
||||
public var charOffsetXStepper:NumericStepper;
|
||||
public var charOffsetYStepper:NumericStepper;
|
||||
public var charHoldTimeStepper:NumericStepper;
|
||||
public var charFlipXCheckbox:Checkbox;
|
||||
public var charScaleStepper:NumericStepper;
|
||||
public var charAntialiasingCheckbox:Checkbox;
|
||||
|
||||
public override function create() {
|
||||
super.create();
|
||||
|
||||
// camera stuff
|
||||
parent.windowCameras[0].resizeScroll = false;
|
||||
camHUD = new FlxCamera(0, 0, 1200, 600, 1);
|
||||
camHUD.pixelPerfectRender = true;
|
||||
camHUD.bgColor = 0;
|
||||
parent.addCamera(camHUD);
|
||||
|
||||
// stage
|
||||
var bg = new FlxSprite(-600, -200).loadAnimatedGraphic(Paths.image('stages/default/stageback'));
|
||||
bg.scrollFactor.set(0.9, 0.9);
|
||||
var stageFront = new FlxSprite(-600, 600).loadAnimatedGraphic(Paths.image('stages/default/stagefront'));
|
||||
silhouetteDad = new Character(100, 100, "dad", false);
|
||||
silhouetteGf = new Character(400, 130, "gf", false);
|
||||
silhouetteGf.scrollFactor.set(0.95, 0.95);
|
||||
silhouetteBf = new Character(770, 100, "bf", true);
|
||||
|
||||
for (e in [silhouetteDad, silhouetteGf, silhouetteBf]) {
|
||||
e.color = 0xFF000000;
|
||||
e.visible = false;
|
||||
e.alpha = 0.25;
|
||||
}
|
||||
|
||||
for (e in [bg, stageFront, silhouetteDad, silhouetteGf, silhouetteBf]) {
|
||||
e.antialiasing = true;
|
||||
add(e);
|
||||
}
|
||||
|
||||
char = new Character(100, 100, curCharacter, false, false);
|
||||
add(char);
|
||||
|
||||
title = 'Character Editor - ${char.curCharacter}.xml';
|
||||
|
||||
// character setup & following
|
||||
var charMidpoint = char.getGraphicMidpoint();
|
||||
camFollow = new FlxObject(0, 0, 2, 2);
|
||||
camFollow.setPosition(charMidpoint.x, charMidpoint.y);
|
||||
add(camFollow);
|
||||
charMidpoint.put();
|
||||
windowCamera.follow(camFollow, LOCKON, 999);
|
||||
|
||||
// loading animations from character
|
||||
animList = [];
|
||||
if (char.xml != null)
|
||||
for(anim in char.xml.nodes.anim)
|
||||
animList.push(anim.extractAnimFromXML());
|
||||
|
||||
// interface setup
|
||||
setupTabView();
|
||||
|
||||
// todo: menu bar handlers
|
||||
menuBar = new MenuBar([
|
||||
{
|
||||
name: "File",
|
||||
options: [
|
||||
{
|
||||
name: "New"
|
||||
},
|
||||
{
|
||||
name: "Open"
|
||||
},
|
||||
{
|
||||
name: "Save"
|
||||
},
|
||||
{
|
||||
name: "Save As..."
|
||||
},
|
||||
{
|
||||
name: "Exit"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Edit",
|
||||
options: [
|
||||
{
|
||||
name: "Add Animation..."
|
||||
},
|
||||
{
|
||||
name: "Delete Animation"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "View",
|
||||
options: [
|
||||
{
|
||||
name: "Lock Camera on Character"
|
||||
},
|
||||
{
|
||||
name: "Reset Camera Position",
|
||||
callback: resetCamPos
|
||||
},
|
||||
{
|
||||
name: "Reset Camera Zoom",
|
||||
callback: resetCamZoom
|
||||
},
|
||||
{
|
||||
name: "Toggle Boyfriend Silhouette",
|
||||
callback: toggleSilBF
|
||||
},
|
||||
{
|
||||
name: "Toggle Dad Silhouette",
|
||||
callback: toggleSilDad
|
||||
},
|
||||
{
|
||||
name: "Toggle Girlfriend Silhouette",
|
||||
callback: toggleSilGF
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Help",
|
||||
options: [
|
||||
{
|
||||
name: "Open Editor Documentation"
|
||||
},
|
||||
{
|
||||
name: "Open Engine Documentation"
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
menuBar.cameras = [camHUD];
|
||||
add(menuBar);
|
||||
}
|
||||
|
||||
public function setupTabView() {
|
||||
tabView = new TabView(800, 20, 400, 580, ["Animation Settings", "Character Settings"]);
|
||||
tabView.updateAnchor(1, 0, [camHUD]);
|
||||
add(tabView);
|
||||
|
||||
addAnimTab();
|
||||
addCharTab();
|
||||
|
||||
refreshAnims();
|
||||
changeAnim(0);
|
||||
}
|
||||
|
||||
public function addAnimTab() {
|
||||
var content:Array<FlxBasic> = [];
|
||||
var label:WindowText = null;
|
||||
|
||||
content.push(label = new WindowText(10, 10, 0, "Animations"));
|
||||
content.push(animsDropDown = new DropDown(10, label.y + label.height, 380, [], function(id) {
|
||||
changeAnim(id);
|
||||
}));
|
||||
|
||||
content.push(label = new WindowText(10, animsDropDown.y + animsDropDown.height + 10, 0, "Animation Name"));
|
||||
content.push(animNameInput = new InputBox(10, label.y + label.height, 380, ""));
|
||||
|
||||
content.push(label = new WindowText(10, animNameInput.y + animNameInput.height + 10, 0, "Animation Prefix"));
|
||||
content.push(animPrefixInput = new InputBox(10, label.y + label.height, 380, ""));
|
||||
|
||||
content.push(animLoopCheckbox = new Checkbox(10, animPrefixInput.y + animPrefixInput.height + 10, 380, "Loop"));
|
||||
|
||||
content.push(label = new WindowText(10, animLoopCheckbox.y + animLoopCheckbox.height + 10, 0, "Animation FPS (Frames per second)"));
|
||||
content.push(animFpsStepper = new NumericStepper(10, label.y + label.height, 380, 0));
|
||||
|
||||
content.push(label = new WindowText(10, animFpsStepper.y + animFpsStepper.height + 10, 0, "Animation Offset (Relative to scale)"));
|
||||
content.push(animOffsetX = new NumericStepper(10, label.y + label.height, 180, 0));
|
||||
content.push(animOffsetY = new NumericStepper(200, label.y + label.height, 180, 0));
|
||||
|
||||
for(e in [animOffsetX, animOffsetY])
|
||||
e.increment = 10;
|
||||
|
||||
for(spr in content)
|
||||
tabView.tabs[0].add(spr);
|
||||
}
|
||||
|
||||
public function addCharTab() {
|
||||
var content:Array<FlxObject> = [];
|
||||
var label:WindowText = null;
|
||||
|
||||
content.push(label = new WindowText(10, 10, 0, "Sprite Name (images/characters/)"));
|
||||
content.push(charSpriteInput = new InputBox(10, label.y + label.height, 380, char.xml.has.sprite ? char.xml.att.sprite : ""));
|
||||
|
||||
content.push(label = new WindowText(10, content.last().y + content.last().height, 0, "Icon Name (images/icons/)"));
|
||||
content.push(charIconInput = new InputBox(10, label.y + label.height, 380, char.icon.getDefault("")));
|
||||
|
||||
content.push(charIsPlayerCheckbox = new Checkbox(10, content.last().y + content.last().height + 10, 380, "Playable character"));
|
||||
content.push(label = new WindowText(10, content.last().y + content.last().height, 380, "(Offsets are automatically fixed when playing as a non-playable character and vice versa)"));
|
||||
charIsPlayerCheckbox.checked = char.xml.getAtt("isPlayer") == "true";
|
||||
|
||||
content.push(charIsGFCheckbox = new Checkbox(10, content.last().y + content.last().height + 10, 380, "Is Girlfriend"));
|
||||
content.push(label = new WindowText(10, content.last().y + content.last().height, 380, "(Characters marked as Girlfriend will replace GF when used as opponent)"));
|
||||
charIsGFCheckbox.checked = char.isGF;
|
||||
|
||||
content.push(charFlipXCheckbox = new Checkbox(10, content.last().y + content.last().height + 10, 380, "Flip Horizontally"));
|
||||
charFlipXCheckbox.checked = char.__baseFlipped != char.isPlayer;
|
||||
|
||||
for(spr in content)
|
||||
tabView.tabs[1].add(spr);
|
||||
}
|
||||
|
||||
public function changeAnim(id:Int) {
|
||||
curAnim = animList[id];
|
||||
if (curAnim == null) return;
|
||||
char.playAnim(curAnim.name, true);
|
||||
|
||||
animNameInput.text = curAnim.name;
|
||||
animPrefixInput.text = curAnim.anim;
|
||||
animLoopCheckbox.setChecked(curAnim.loop);
|
||||
animFpsStepper.value = curAnim.fps;
|
||||
animOffsetX.value = curAnim.x;
|
||||
animOffsetY.value = curAnim.y;
|
||||
}
|
||||
|
||||
public function refreshAnims() {
|
||||
animListNames = [for(e in animList) e.name];
|
||||
animsDropDown.options = animListNames;
|
||||
animsDropDown.onSelectionChange(0);
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
if (parent.focused) {
|
||||
if (FlxG.keys.pressed.RIGHT) camFollow.x += elapsed * 500;
|
||||
if (FlxG.keys.pressed.LEFT) camFollow.x -= elapsed * 500;
|
||||
if (FlxG.keys.pressed.DOWN) camFollow.y += elapsed * 500;
|
||||
if (FlxG.keys.pressed.UP) camFollow.y -= elapsed * 500;
|
||||
}
|
||||
|
||||
if (curAnim != null) {
|
||||
// animation updating
|
||||
var shouldUpdate = false;
|
||||
var oldName:String = curAnim.name;
|
||||
|
||||
var updateListAsWell = shouldUpdate = (curAnim.name != (curAnim.name = animNameInput.text));
|
||||
shouldUpdate = (curAnim.anim != (curAnim.anim = animPrefixInput.text)) || shouldUpdate;
|
||||
shouldUpdate = (curAnim.fps != (curAnim.fps = Std.int(animFpsStepper.value))) || shouldUpdate;
|
||||
shouldUpdate = (curAnim.loop != (curAnim.loop = animLoopCheckbox.checked)) || shouldUpdate;
|
||||
shouldUpdate = (curAnim.x != (curAnim.x = animOffsetX.value)) || shouldUpdate;
|
||||
shouldUpdate = (curAnim.y != (curAnim.y = animOffsetY.value)) || shouldUpdate;
|
||||
|
||||
if (shouldUpdate)
|
||||
updateCurAnim(oldName, updateListAsWell);
|
||||
}
|
||||
|
||||
char.isPlayer = char.playerOffsets = charIsPlayerCheckbox.checked;
|
||||
char.isGF = charIsPlayerCheckbox.checked;
|
||||
char.flipX = char.__baseFlipped = (charFlipXCheckbox.checked != char.isPlayer);
|
||||
char.x = charIsPlayerCheckbox.checked ? 770 : 100;
|
||||
}
|
||||
|
||||
public function updateCurAnim(?oldName:String, updateListAsWell:Bool = false) {
|
||||
if (oldName == null)
|
||||
oldName = char.animation.curAnim != null ? char.animation.curAnim.name : curAnim.name;
|
||||
|
||||
char.animation.remove(oldName);
|
||||
char.animation.curAnim = null;
|
||||
|
||||
XMLUtil.addAnimToSprite(char, curAnim);
|
||||
|
||||
char.playAnim(curAnim.name, true);
|
||||
}
|
||||
|
||||
public override function onWindowResize(width:Int, height:Int) {
|
||||
tabView.resize(400, height - 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* =========== CONTEXT MENU OPTIONS ===========
|
||||
*/
|
||||
|
||||
/**
|
||||
* View
|
||||
*/
|
||||
public function resetCamPos() {
|
||||
var pos = char.getCameraPosition();
|
||||
camFollow.setPosition(pos.x, pos.y);
|
||||
}
|
||||
public function resetCamZoom() {
|
||||
windowCamera.zoom = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Silhouettes
|
||||
*/
|
||||
public function toggleSilBF() silhouetteBf.visible = !silhouetteBf.visible;
|
||||
public function toggleSilDad() silhouetteDad.visible = !silhouetteDad.visible;
|
||||
public function toggleSilGF() silhouetteGf.visible = !silhouetteGf.visible;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package funkin.desktop.editors;
|
||||
|
||||
class CommandPrompt extends WindowContent {
|
||||
public function new() {
|
||||
super("Command Prompt", 100, 100, 960, 480);
|
||||
}
|
||||
|
||||
public override function create() {
|
||||
super.create();
|
||||
windowCamera.bgColor = 0xFF000000;
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package funkin.desktop.editors;
|
||||
|
||||
import flixel.math.FlxPoint;
|
||||
|
||||
class EditorPlayState extends WindowContent {
|
||||
var state:PlayState;
|
||||
|
||||
public function new() {
|
||||
super("PlayState", 120, 120, 1280, 720);
|
||||
state = new PlayState();
|
||||
}
|
||||
public override function create() {
|
||||
super.create();
|
||||
|
||||
beforeStateShit();
|
||||
state.camera = parent.windowCameras[0].camera;
|
||||
state.create();
|
||||
afterStateShit();
|
||||
|
||||
parent.windowCameras[0].resizeScroll = false;
|
||||
parent.windowCameras.push(
|
||||
{
|
||||
camera: state.camHUD,
|
||||
width: 1280,
|
||||
height: 720,
|
||||
resizeScroll: true
|
||||
}
|
||||
);
|
||||
parent.move(winX, winY);
|
||||
parent.resize(1280, 720);
|
||||
beforeStateShit();
|
||||
state.createPost();
|
||||
afterStateShit();
|
||||
}
|
||||
var oldSize = FlxPoint.get(FlxG.width, FlxG.height);
|
||||
var oldCamList:Array<FlxCamera>;
|
||||
var oldCam:FlxCamera;
|
||||
|
||||
public function beforeStateShit() {
|
||||
oldSize.set(FlxG.width, FlxG.height);
|
||||
@:privateAccess
|
||||
FlxG.width = 1280;
|
||||
@:privateAccess
|
||||
FlxG.height = 720;
|
||||
|
||||
oldCamList = FlxG.cameras.list;
|
||||
oldCam = FlxG.camera;
|
||||
@:privateAccess
|
||||
FlxG.cameras.list = [for(e in parent.windowCameras) e.camera];
|
||||
FlxG.camera = parent.windowCameras[0].camera;
|
||||
}
|
||||
public function afterStateShit() {
|
||||
@:privateAccess
|
||||
FlxG.width = Std.int(oldSize.x);
|
||||
@:privateAccess
|
||||
FlxG.height = Std.int(oldSize.y);
|
||||
|
||||
parent.windowCameras = [for(e in FlxG.cameras.list) {
|
||||
camera: e,
|
||||
width: 1280,
|
||||
height: 720,
|
||||
resizeScroll: false
|
||||
}];
|
||||
@:privateAccess
|
||||
FlxG.cameras.list = oldCamList;
|
||||
FlxG.camera = oldCam;
|
||||
|
||||
oldCamList = null;
|
||||
oldCam = null;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
beforeStateShit();
|
||||
super.update(elapsed);
|
||||
@:privateAccess
|
||||
FlxG.cameras.update(elapsed);
|
||||
state.tryUpdate(elapsed);
|
||||
afterStateShit();
|
||||
}
|
||||
|
||||
public override function destroy() {
|
||||
beforeStateShit();
|
||||
super.destroy();
|
||||
state.destroy();
|
||||
afterStateShit();
|
||||
}
|
||||
|
||||
public override function draw() {
|
||||
beforeStateShit();
|
||||
super.draw();
|
||||
state.draw();
|
||||
afterStateShit();
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package funkin.desktop.editors;
|
||||
|
||||
import flixel.util.FlxDestroyUtil.IFlxDestroyable;
|
||||
import flixel.addons.ui.FlxUIText;
|
||||
|
||||
class HelloWorld extends WindowContent {
|
||||
public override function new() {
|
||||
super("Test Window", 100, 100, 640, 480);
|
||||
}
|
||||
|
||||
public override function create() {
|
||||
super.create();
|
||||
|
||||
var helloWorldText = new WindowText(0, 0, 0, "Hello, World!");
|
||||
helloWorldText.scrollFactor.set(0.5, 0.5);
|
||||
helloWorldText.cameraCenter(camera);
|
||||
add(helloWorldText);
|
||||
|
||||
var t = new WindowText(0, 0, 0, "Bottom right text!");
|
||||
t.setPosition(630 - t.width, 470 - t.height);
|
||||
t.scrollFactor.set(1, 1);
|
||||
add(t);
|
||||
|
||||
var tabs = new TabView(330, 10, 300, 500, ["Tab 1", "Tab 2", "Tab 3"]);
|
||||
tabs.updateAnchor(1, 0);
|
||||
add(tabs);
|
||||
|
||||
|
||||
var checkbox = new Checkbox(10, 40, 0, "Test Checkbox", CHECKED);
|
||||
var text = new WindowText(10, 10, 180, "Stuff in page 1");
|
||||
tabs.tabs[0].add(text);
|
||||
tabs.tabs[0].add(checkbox);
|
||||
|
||||
var text2 = new WindowText(10, 10, 180, "Stuff in page 2");
|
||||
tabs.tabs[1].add(text2);
|
||||
|
||||
var butt = new Button(10, 10, "Test", function() {
|
||||
parent.showMessage("Test", "Test", ERROR);
|
||||
});
|
||||
butt.scrollFactor.set();
|
||||
add(butt);
|
||||
}
|
||||
|
||||
public var time:Float = 0;
|
||||
public var coolAssMode:Bool = false;
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
time += elapsed;
|
||||
|
||||
if (FlxG.keys.justPressed.M) coolAssMode = !coolAssMode;
|
||||
|
||||
if (coolAssMode) {
|
||||
width = 500 + Std.int(Math.cos(time * Math.PI) * 250);
|
||||
height = 500 + Std.int(Math.sin(time * Math.PI) * 250);
|
||||
}
|
||||
parent.updateWindowFrame();
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package funkin.desktop.editors;
|
||||
|
||||
import flixel.util.typeLimit.OneOfTwo;
|
||||
import flixel.util.FlxDestroyUtil.IFlxDestroyable;
|
||||
import flixel.addons.ui.FlxUIText;
|
||||
|
||||
class MessageBox extends WindowContent {
|
||||
public var caption:String;
|
||||
public var message:String;
|
||||
public var msgIcon:MessageBoxIcon;
|
||||
public var callback:Int->Void = null;
|
||||
private var __buttons:Array<OneOfTwo<String, Butt>> = null;
|
||||
|
||||
public override function new(caption:String, message:String, icon:MessageBoxIcon, ?buttons:Array<OneOfTwo<String, Butt>>, ?callback:Int->Void) {
|
||||
super(caption, 100, 100, 500, 500);
|
||||
this.caption = caption;
|
||||
this.message = message;
|
||||
this.msgIcon = icon;
|
||||
this.callback = callback;
|
||||
this.__buttons = buttons;
|
||||
}
|
||||
|
||||
public override function create() {
|
||||
super.create();
|
||||
parent.canMinimize = parent.resizeable = false;
|
||||
var text = new WindowText(10, 10, 0, message);
|
||||
if (text.width > 500)
|
||||
text.fieldWidth = 500;
|
||||
add(text);
|
||||
setSize(Std.int(Math.max(text.width + 20, 240)), Std.int(text.height + 20));
|
||||
|
||||
|
||||
if (__buttons == null || __buttons.length <= 0) __buttons = ["OK"];
|
||||
|
||||
var firstButt:Button = null;
|
||||
for(k=>b in __buttons) {
|
||||
var label:String = null;
|
||||
var callback:Void->Void = null;
|
||||
if (b is String) {
|
||||
label = cast(b, String);
|
||||
} else if (b is Dynamic) {
|
||||
label = Reflect.field(b, "label");
|
||||
callback = Reflect.field(b, "callback");
|
||||
}
|
||||
var button = new Button(490, 490, label, function() {
|
||||
parent.close();
|
||||
if (callback != null) callback();
|
||||
if (this.callback != null) this.callback(k);
|
||||
});
|
||||
button.x -= button.width;
|
||||
button.y -= button.height;
|
||||
button.scrollFactor.set(1, 1);
|
||||
add(button);
|
||||
if (firstButt == null) firstButt = button;
|
||||
}
|
||||
setSize(Std.int(width), Std.int(height + firstButt.height + 10));
|
||||
}
|
||||
}
|
||||
|
||||
@:enum
|
||||
abstract MessageBoxIcon(Int) {
|
||||
var ERROR = 0;
|
||||
var ALERT = 1;
|
||||
var INFORMATION = 2;
|
||||
var QUESTION = 3;
|
||||
}
|
||||
|
||||
// HAHA BUTT!! *minion laugh*
|
||||
typedef Butt = {
|
||||
var label:String;
|
||||
@:optional var callback:Void->Void;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package funkin.desktop.editors;
|
||||
|
||||
import funkin.desktop.windows.*;
|
||||
import funkin.desktop.sprites.*;
|
||||
@@ -1,3 +0,0 @@
|
||||
using funkin.desktop.DesktopUtils;
|
||||
using funkin.desktop.windows.ContextMenu;
|
||||
using funkin.desktop.DesktopMain;
|
||||
@@ -1,126 +0,0 @@
|
||||
package funkin.desktop.sprites;
|
||||
|
||||
import funkin.desktop.DesktopMain.IDesktopFocusableObject;
|
||||
import funkin.desktop.theme.Theme;
|
||||
import flixel.addons.ui.FlxUIText;
|
||||
import flixel.math.FlxPoint;
|
||||
import funkin.desktop.windows.WindowGroup;
|
||||
|
||||
using funkin.desktop.DesktopMain;
|
||||
|
||||
class Button extends FlxObject implements IDesktopFocusableObject {
|
||||
public var callback:Void->Void;
|
||||
|
||||
public var disabled:Bool = false;
|
||||
|
||||
public var frame:Int = 0;
|
||||
|
||||
public var normalSprite:SpliceSprite;
|
||||
public var hoverSprite:SpliceSprite;
|
||||
public var pressedSprite:SpliceSprite;
|
||||
public var disabledSprite:SpliceSprite;
|
||||
|
||||
public var label:WindowText;
|
||||
|
||||
private override function get_width() {
|
||||
return normalSprite.width;
|
||||
}
|
||||
|
||||
private override function get_height() {
|
||||
return normalSprite.height;
|
||||
}
|
||||
|
||||
public function new(x:Float, y:Float, text:String = "", callback:Void->Void, ?normalButton:ThemeData, ?hoverButton:ThemeData, ?pressedButton:ThemeData, ?disabledButton:ThemeData) {
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = 75;
|
||||
this.height = 24;
|
||||
this.callback = callback;
|
||||
|
||||
scrollFactor.set();
|
||||
|
||||
if (normalButton == null) normalButton = DesktopMain.theme.normalButton;
|
||||
if (hoverButton == null) hoverButton = DesktopMain.theme.hoverButton;
|
||||
if (pressedButton == null) pressedButton = DesktopMain.theme.pressedButton;
|
||||
if (disabledButton == null) disabledButton = DesktopMain.theme.disabledButton;
|
||||
|
||||
normalSprite = new SpliceSprite(Paths.image(normalButton.sprite), x, y, 75, 24, normalButton.left, normalButton.top, normalButton.bottom, normalButton.right);
|
||||
hoverSprite = new SpliceSprite(Paths.image(hoverButton.sprite), x, y, 75, 24, hoverButton.left, hoverButton.top, hoverButton.bottom, hoverButton.right);
|
||||
pressedSprite = new SpliceSprite(Paths.image(pressedButton.sprite), x, y, 75, 24, pressedButton.left, pressedButton.top, pressedButton.bottom, pressedButton.right);
|
||||
disabledSprite = new SpliceSprite(Paths.image(disabledButton.sprite), x, y, 75, 24, disabledButton.left, disabledButton.top, disabledButton.bottom, disabledButton.right);
|
||||
|
||||
label = new WindowText(0, 0, 75, text);
|
||||
label.alignment = CENTER;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
var mouseInput = DesktopMain.mouseInput;
|
||||
if (mouseInput.overlaps(normalSprite, camera)) {
|
||||
if (mouseInput.justReleased) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mouseInput.justPressed || mouseInput.pressed) {
|
||||
this.setFocus();
|
||||
frame = 2;
|
||||
}
|
||||
else
|
||||
frame = 1;
|
||||
mouseInput.cancel();
|
||||
} else
|
||||
frame = 0;
|
||||
|
||||
if (disabled) frame = 3;
|
||||
|
||||
for(e in [normalSprite, hoverSprite, pressedSprite, disabledSprite])
|
||||
e.update(elapsed);
|
||||
|
||||
label.color = switch(frame) {
|
||||
case 1: DesktopMain.theme.hoverButton.textColor;
|
||||
case 2: DesktopMain.theme.pressedButton.textColor;
|
||||
case 3: DesktopMain.theme.disabledButton.textColor;
|
||||
default: DesktopMain.theme.normalButton.textColor;
|
||||
}
|
||||
}
|
||||
|
||||
public override function destroy() {
|
||||
DesktopMain.loseFocus(this);
|
||||
|
||||
for(e in [normalSprite, hoverSprite, pressedSprite, disabledSprite])
|
||||
e.destroy();
|
||||
scrollFactor.put();
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
public function resize(width:Float, height:Float) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
normalSprite.resize(width, height);
|
||||
label.fieldWidth = width;
|
||||
}
|
||||
public override function draw() {
|
||||
super.draw();
|
||||
var spr = switch(frame) {
|
||||
case 1: hoverSprite;
|
||||
case 2: pressedSprite;
|
||||
case 3: disabledSprite;
|
||||
default: normalSprite;
|
||||
};
|
||||
spr.resize(width, height);
|
||||
for(sprite in [spr, label])
|
||||
sprite.copyProperties(this);
|
||||
spr.draw();
|
||||
label.y += (height - label.height) / 2;
|
||||
label.draw();
|
||||
additionalDraw();
|
||||
}
|
||||
|
||||
public function additionalDraw() {}
|
||||
|
||||
|
||||
public function onFocus() {}
|
||||
public function onFocusLost() {}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package funkin.desktop.sprites;
|
||||
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.text.FlxText;
|
||||
|
||||
class Checkbox extends WindowText {
|
||||
public var checked:CheckState = UNCHECKED;
|
||||
public var disabled:Bool = false;
|
||||
public var checkboxSprite:FlxSprite;
|
||||
|
||||
public function new(x:Float, y:Float, w:Float, t:String, checked:CheckState = UNCHECKED) {
|
||||
super(x, y, w, t);
|
||||
this.checked = checked;
|
||||
offset.x -= 20;
|
||||
|
||||
var t = DesktopMain.theme.checkbox;
|
||||
|
||||
checkboxSprite = new FlxSprite(0, (20 - t.height) / 2);
|
||||
checkboxSprite.loadGraphic(Paths.image(t.sprite), true, Std.int(t.width), Std.int(t.height));
|
||||
checkboxSprite.animation.add("checkbox", [for(i in 0...checkboxSprite.frames.frames.length) i], 0, true);
|
||||
checkboxSprite.animation.play("checkbox");
|
||||
|
||||
scrollFactor.set();
|
||||
}
|
||||
|
||||
public function setChecked(checked:Bool) {
|
||||
this.checked = cast checked;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
checkboxSprite.update(elapsed);
|
||||
|
||||
var overlaps = DesktopMain.mouseInput.overlapsRect(this, new FlxRect(x, y, width + 20, height), camera);
|
||||
var pressed = DesktopMain.mouseInput.pressed;
|
||||
|
||||
if (overlaps) {
|
||||
// cancel so that sprites in the bg dont get hovered as well
|
||||
if (!disabled && DesktopMain.mouseInput.justPressed) {
|
||||
checked = switch(checked) {
|
||||
case CHECKED | BOTH:
|
||||
UNCHECKED;
|
||||
case UNCHECKED:
|
||||
CHECKED;
|
||||
}
|
||||
}
|
||||
DesktopMain.mouseInput.cancel();
|
||||
}
|
||||
|
||||
checkboxSprite.animation.curAnim.curFrame = (switch(checked) {
|
||||
case UNCHECKED: 0;
|
||||
case CHECKED: 1;
|
||||
case BOTH: 2;
|
||||
}) + (disabled ? 9 : (overlaps ? (pressed ? 6 : 3) : 0));
|
||||
}
|
||||
|
||||
public override function draw() {
|
||||
checkboxSprite.copyProperties(this);
|
||||
rotOffset.y = (this.height - checkboxSprite.height) / 2;
|
||||
super.draw();
|
||||
checkboxSprite.draw();
|
||||
}
|
||||
}
|
||||
|
||||
@:enum
|
||||
abstract CheckState(Null<Bool>) from Null<Bool> to Null<Bool> from Bool to Bool {
|
||||
var CHECKED:CheckState = true;
|
||||
var UNCHECKED:CheckState = false;
|
||||
var BOTH:CheckState = null;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package funkin.desktop.sprites;
|
||||
|
||||
import funkin.desktop.theme.Theme.ThemeData;
|
||||
import flixel.math.FlxPoint;
|
||||
|
||||
class DropDown extends Button {
|
||||
public var selectedIndex:Int = -1;
|
||||
public var onChange:Int->Void;
|
||||
public var options:Array<String>;
|
||||
|
||||
public function new(x:Float, y:Float, w:Float, options:Array<String>, onChange:Int->Void, curId:Int = 0, ?normalButton:ThemeData, ?hoverButton:ThemeData, ?pressedButton:ThemeData, ?disabledButton:ThemeData) {
|
||||
super(x, y, "", onClick, normalButton, hoverButton, pressedButton, disabledButton);
|
||||
this.options = options;
|
||||
onSelectionChange(curId);
|
||||
this.onChange = onChange;
|
||||
}
|
||||
|
||||
public function onClick() {
|
||||
var pos:FlxPoint = getScreenPosition(null, camera);
|
||||
pos.y += height;
|
||||
|
||||
var camPos = camera != null ? FlxPoint.get(camera.x, camera.y) : FlxPoint.get();
|
||||
|
||||
ContextMenu.open(pos.x + camPos.x, pos.y + camPos.y, [for(o in options) {
|
||||
{
|
||||
name: o
|
||||
}
|
||||
}], onSelectionChange);
|
||||
|
||||
pos.put();
|
||||
camPos.put();
|
||||
}
|
||||
|
||||
public function onSelectionChange(id:Int) {
|
||||
selectedIndex = id;
|
||||
label.text = options[id];
|
||||
if (onChange != null)
|
||||
onChange(id);
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package funkin.desktop.sprites;
|
||||
|
||||
import openfl.ui.Keyboard;
|
||||
import openfl.events.KeyboardEvent;
|
||||
import lime.app.Application;
|
||||
|
||||
class InputBox extends Button implements IDesktopInputObject {
|
||||
public var index:Int = 0;
|
||||
public static var insertMode:Bool = false;
|
||||
|
||||
public var text(get, set):String;
|
||||
private inline function set_text(t:String):String
|
||||
return label.text = t;
|
||||
private inline function get_text():String
|
||||
return label.text;
|
||||
|
||||
public var onChange:Void->Void;
|
||||
public var onConfirm:Void->Void;
|
||||
|
||||
public function new(x:Float, y:Float, w:Float, t:String, ?onChange:Void->Void) {
|
||||
super(x, y, t, function() {
|
||||
setIndex(label.text.length);
|
||||
disabled = true;
|
||||
}, DesktopMain.theme.textbox, DesktopMain.theme.textboxHover, DesktopMain.theme.textboxPressed, DesktopMain.theme.textboxFocused);
|
||||
this.resize(w, height);
|
||||
this.label.alignment = LEFT;
|
||||
FlxG.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
|
||||
Application.current.window.onTextInput.add(onTextInput);
|
||||
}
|
||||
|
||||
|
||||
private function onKeyDown(event:KeyboardEvent) {
|
||||
if (!this.hasFocus()) return;
|
||||
switch(event.keyCode) {
|
||||
case Keyboard.ESCAPE:
|
||||
this.loseFocus();
|
||||
case Keyboard.INSERT:
|
||||
insertMode = !insertMode;
|
||||
case Keyboard.LEFT:
|
||||
changeIndex(-1);
|
||||
case Keyboard.RIGHT:
|
||||
changeIndex(1);
|
||||
case Keyboard.HOME:
|
||||
setIndex(0);
|
||||
case Keyboard.END:
|
||||
setIndex(text.length);
|
||||
case Keyboard.DELETE:
|
||||
text = text.substr(0, index) + text.substring(index + 1, text.length);
|
||||
onTextInput("");
|
||||
case Keyboard.BACKSPACE:
|
||||
text = text.substr(0, index <= 0 ? 0 : index - 1) + text.substring(index, text.length);
|
||||
changeIndex(-1);
|
||||
onTextInput("");
|
||||
case Keyboard.ENTER | Keyboard.NUMPAD_ENTER:
|
||||
if (onChange != null)
|
||||
onChange();
|
||||
if (onConfirm != null)
|
||||
onConfirm();
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
private function onTextInput(input:String) {
|
||||
if (!this.hasFocus()) return;
|
||||
|
||||
if (input.length > 0) {
|
||||
text = text.substr(0, index) + input + text.substring(index, text.length);
|
||||
|
||||
if (!insertMode)
|
||||
index += input.length;
|
||||
}
|
||||
|
||||
if (onChange != null)
|
||||
onChange();
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
if (DesktopMain.mouseInput.justPressed && !DesktopMain.mouseInput.overlaps(this, camera))
|
||||
this.loseFocus();
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
public override function onFocusLost() {
|
||||
super.onFocusLost();
|
||||
if (disabled != (disabled = false)) {
|
||||
if (onChange != null)
|
||||
onChange();
|
||||
if (onConfirm != null)
|
||||
onConfirm();
|
||||
}
|
||||
}
|
||||
|
||||
public inline function changeIndex(change:Int) {
|
||||
setIndex(Std.int(FlxMath.bound(index + change, 0, label.text.length)));
|
||||
}
|
||||
|
||||
public inline function setIndex(index:Int) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public override function destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package funkin.desktop.sprites;
|
||||
|
||||
import flixel.math.FlxPoint;
|
||||
import funkin.desktop.windows.WindowGroup;
|
||||
|
||||
class MenuBar extends WindowGroup<FlxBasic> {
|
||||
public var spr:FlxSprite;
|
||||
public var buttons:Array<Button> = [];
|
||||
public function new(trees:Array<TopMenuTree>) {
|
||||
super();
|
||||
|
||||
spr = new FlxSprite(0, 0);
|
||||
spr.loadGraphic(Paths.image(DesktopMain.theme.menuBar.sprite));
|
||||
add(spr);
|
||||
|
||||
var lastX:Float = 0;
|
||||
for(t in trees) {
|
||||
var b:Button = null;
|
||||
b = new Button(lastX, 0, t.name, function() {
|
||||
var pos:FlxPoint = b.getScreenPosition(null, camera);
|
||||
pos.y += b.height;
|
||||
|
||||
var camPos = camera != null ? FlxPoint.get(camera.x, camera.y) : FlxPoint.get();
|
||||
|
||||
ContextMenu.open(pos.x + camPos.x, pos.y + camPos.y, t.options, function(i) {});
|
||||
|
||||
pos.put();
|
||||
});
|
||||
b.label.fieldWidth = 0;
|
||||
@:privateAccess b.label._regen = true;
|
||||
|
||||
b.resize(b.label.width + 20, 20);
|
||||
lastX = b.x + b.width;
|
||||
|
||||
b.normalSprite.visible = false;
|
||||
buttons.push(b);
|
||||
add(b);
|
||||
}
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
|
||||
spr.setGraphicSize(FlxG.width, 20);
|
||||
spr.updateHitbox();
|
||||
}
|
||||
}
|
||||
|
||||
typedef TopMenuTree = {
|
||||
var name:String;
|
||||
var options:Array<ContextOption>;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package funkin.desktop.sprites;
|
||||
|
||||
|
||||
// TODO: FIX MEMORY GOING BRRRRRRRRRRRRRRRRRRRRR
|
||||
class NumericStepper extends InputBox {
|
||||
public var decimals:Int = 0;
|
||||
public var increment:Float = 1;
|
||||
|
||||
@:isVar public var value(get, set):Float = 0;
|
||||
|
||||
public var onValueChange:Void->Void;
|
||||
|
||||
public var addButton:Button;
|
||||
public var subButton:Button;
|
||||
|
||||
public function new(x:Float, y:Float, w:Float, v:Float, ?onValueChange:Void->Void) {
|
||||
super(x, y, w, Std.string(v));
|
||||
addButton = new Button(w - (height * 2), 0, "+", onAdd);
|
||||
addButton.resize(height, height);
|
||||
|
||||
subButton = new Button(w - (height), 0, "-", onSub);
|
||||
subButton.resize(height, height);
|
||||
|
||||
onConfirm = onManualChange;
|
||||
}
|
||||
|
||||
public override function resize(width:Float, height:Float) {
|
||||
super.resize(width - (height * 2), height);
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
addButton.update(elapsed);
|
||||
subButton.update(elapsed);
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
public override function additionalDraw() {
|
||||
addButton.copyProperties(this);
|
||||
subButton.copyProperties(this);
|
||||
addButton.x += width;
|
||||
subButton.x += width + height;
|
||||
|
||||
addButton.draw();
|
||||
subButton.draw();
|
||||
}
|
||||
|
||||
private inline function onSub()
|
||||
value--;
|
||||
|
||||
private inline function onAdd()
|
||||
value++;
|
||||
|
||||
private function onManualChange() {
|
||||
var v = Std.parseFloat(text);
|
||||
if (!v.isNaN()) {
|
||||
value = round(v);
|
||||
} else {
|
||||
set_value(value);
|
||||
}
|
||||
}
|
||||
|
||||
private function set_value(nv:Float) {
|
||||
if (this.value != (this.value = nv))
|
||||
if (onValueChange != null)
|
||||
onValueChange();
|
||||
text = Std.string(round(this.value));
|
||||
return this.value;
|
||||
}
|
||||
|
||||
private inline function get_value()
|
||||
return this.value;
|
||||
|
||||
private inline function round(value:Float) {
|
||||
return decimals <= 0 ? Std.int(value) : FlxMath.roundDecimal(value, decimals);
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
package funkin.desktop.sprites;
|
||||
|
||||
import openfl.display.BitmapData;
|
||||
import openfl.geom.Rectangle;
|
||||
import openfl.geom.Point;
|
||||
import flixel.system.FlxAssets.FlxGraphicAsset;
|
||||
|
||||
class SpliceSprite extends FlxObject {
|
||||
public var topLeft:FlxSprite = new FlxSprite();
|
||||
public var left:FlxSprite = new FlxSprite();
|
||||
public var bottomLeft:FlxSprite = new FlxSprite();
|
||||
public var bottom:FlxSprite = new FlxSprite();
|
||||
public var bottomRight:FlxSprite = new FlxSprite();
|
||||
public var right:FlxSprite = new FlxSprite();
|
||||
public var topRight:FlxSprite = new FlxSprite();
|
||||
public var top:FlxSprite = new FlxSprite();
|
||||
public var middle:FlxSprite = new FlxSprite();
|
||||
|
||||
public var __internalSprite:FlxSprite;
|
||||
public var slice:Array<Int> = [0, 0, 0, 0];
|
||||
|
||||
public function new(spr:FlxGraphicAsset, x:Float, y:Float, width:Float, height:Float, left:Float = 5, top:Float = 5, bottom:Float = 5, right:Float = 5) {
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
scrollFactor.set();
|
||||
|
||||
__internalSprite = new FlxSprite(0, 0, spr);
|
||||
|
||||
slice = [Std.int(left), Std.int(bottom), Std.int(top), Std.int(right)];
|
||||
// for(e in [topLeft, left, bottomLeft, bottom, bottomRight, right, topRight, top]) {
|
||||
// e.loadGraphic(spr);
|
||||
// }
|
||||
updateRects();
|
||||
}
|
||||
|
||||
public function updateRects() {
|
||||
var parts = [topLeft, left, bottomLeft, bottom, bottomRight, right, topRight, top];
|
||||
var _left:Int = slice[0];
|
||||
var _down:Int = slice[1];
|
||||
var _up:Int = slice[2];
|
||||
var _right:Int = slice[3];
|
||||
var _height:Int = __internalSprite.frameHeight;
|
||||
var _width:Int = __internalSprite.frameWidth;
|
||||
|
||||
topLeft.pixels = new BitmapData(_left, _up, true, 0);
|
||||
left.pixels = new BitmapData(_left, _height - _up - _down, true, 0);
|
||||
bottomLeft.pixels = new BitmapData(_left, _down, true, 0);
|
||||
bottom.pixels = new BitmapData(_width - _left - _right, _down, true, 0);
|
||||
bottomRight.pixels = new BitmapData(_right, _down, true, 0);
|
||||
right.pixels = new BitmapData(_right, _height - _up - _down, true, 0);
|
||||
topRight.pixels = new BitmapData(_right, _up, true, 0);
|
||||
top.pixels = new BitmapData(_width - _left - _right, _up, true, 0);
|
||||
middle.pixels = new BitmapData(_width - _left - _right, _height - _up - _down, true, 0);
|
||||
|
||||
|
||||
for(e in parts) e.pixels.lock();
|
||||
|
||||
var pos = new Point(0, 0);
|
||||
topLeft.pixels.copyPixels(__internalSprite.pixels, new Rectangle(0, 0, _left, _up), pos);
|
||||
left.pixels.copyPixels(__internalSprite.pixels, new Rectangle(0, _up, _left, _height - _up - _down), pos);
|
||||
bottomLeft.pixels.copyPixels(__internalSprite.pixels, new Rectangle(0, _height - _down, _left, _down), pos);
|
||||
bottom.pixels.copyPixels(__internalSprite.pixels, new Rectangle(_left, _height - _down, _width - _left - _right, _down), pos);
|
||||
bottomRight.pixels.copyPixels(__internalSprite.pixels, new Rectangle(_width - _right, _height - _down, _right, _down), pos);
|
||||
right.pixels.copyPixels(__internalSprite.pixels, new Rectangle(_width - _right, _up, _right, _height - _down - _up), pos);
|
||||
topRight.pixels.copyPixels(__internalSprite.pixels, new Rectangle(_width - _right, 0, _right, _up), pos);
|
||||
top.pixels.copyPixels(__internalSprite.pixels, new Rectangle(_left, 0, _width - _left - _right, _up), pos);
|
||||
middle.pixels.copyPixels(__internalSprite.pixels, new Rectangle(_left, _up, _width - _left - _right, _height - _up - _down), pos);
|
||||
|
||||
for(e in parts) e.pixels.unlock();
|
||||
}
|
||||
|
||||
public override function destroy() {
|
||||
for(e in [topLeft, left, bottomLeft, bottom, bottomRight, right, topRight, top, __internalSprite])
|
||||
e.destroy();
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
public function resize(width:Float, height:Float) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public override function draw() {
|
||||
if (!visible) return;
|
||||
super.draw();
|
||||
var parts = [topLeft, left, bottomLeft, bottom, bottomRight, right, topRight, top, middle];
|
||||
|
||||
var _left:Int = slice[0];
|
||||
var _down:Int = slice[1];
|
||||
var _up:Int = slice[2];
|
||||
var _right:Int = slice[3];
|
||||
|
||||
// left
|
||||
topLeft.setPosition(x, y);
|
||||
left.setPosition(x, y + _up);
|
||||
left.setSpriteSize(_left, height - _up - _down);
|
||||
bottomLeft.setPosition(x, y + height - _down);
|
||||
|
||||
// top
|
||||
top.setPosition(x + _left, y);
|
||||
top.setSpriteSize(width - _left - _right, _up);
|
||||
|
||||
// bottom
|
||||
bottom.setPosition(x + _left, y + height - _down);
|
||||
bottom.setSpriteSize(width - _left - _right, _down);
|
||||
|
||||
// right
|
||||
topRight.setPosition(x + (width - _right), y);
|
||||
right.setPosition(x + (width - _right), y + _up);
|
||||
right.setSpriteSize(_right, height - _up - _down);
|
||||
bottomRight.setPosition(x + (width - _right), y + height - _down);
|
||||
|
||||
// middle by dj snake
|
||||
middle.setPosition(x + _left, y + _up);
|
||||
middle.setSpriteSize(width - _left - _right, height - _up - _down);
|
||||
|
||||
for(e in parts) {
|
||||
e.cameras = cameras;
|
||||
e.scrollFactor.set(scrollFactor.x, scrollFactor.y);
|
||||
e.draw();
|
||||
}
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
for(e in [topLeft, left, bottomLeft, bottom, bottomRight, right, topRight, top])
|
||||
e.update(elapsed);
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
package funkin.desktop.sprites;
|
||||
|
||||
import flixel.math.FlxRect;
|
||||
import funkin.desktop.windows.WindowGroup;
|
||||
|
||||
class TabView extends WindowGroup<FlxBasic> {
|
||||
public var tabBG:SpliceSprite;
|
||||
public var tabButtons:Array<Button> = [];
|
||||
public var tabs:Array<WindowGroup<FlxBasic>> = [];
|
||||
public var bg:SpliceSprite;
|
||||
|
||||
public var selectedTab:Int = 0;
|
||||
|
||||
public var width:Float;
|
||||
public var height:Float;
|
||||
|
||||
public function new(x:Float, y:Float, width:Float, height:Float, tabs:Array<String>) {
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
var tabBG = DesktopMain.theme.tabBackground;
|
||||
bg = new SpliceSprite(Paths.image(tabBG.sprite), x, y, 75, 24, tabBG.left, tabBG.top, tabBG.bottom, tabBG.right);
|
||||
add(bg);
|
||||
for(k=>t in tabs) {
|
||||
// BUTTON
|
||||
var b = new Button(0, 0, t, function() {
|
||||
switchTab(k);
|
||||
}, DesktopMain.theme.tabButtonUnselected, DesktopMain.theme.tabButtonHover, DesktopMain.theme.tabButtonPressed, DesktopMain.theme.tabButtonSelected);
|
||||
|
||||
tabButtons.push(b);
|
||||
add(b);
|
||||
|
||||
// TAB
|
||||
var tab = new WindowGroup<FlxBasic>();
|
||||
tab.y += b.height;
|
||||
this.tabs.push(tab);
|
||||
add(tab);
|
||||
}
|
||||
resize(width, height);
|
||||
switchTab(0);
|
||||
}
|
||||
|
||||
public function resize(width:Float, height:Float) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
updateButtons();
|
||||
updateBG();
|
||||
}
|
||||
|
||||
public function updateButtons() {
|
||||
var bWidth:Float = Math.floor(width / tabs.length);
|
||||
for(k=>b in tabButtons) {
|
||||
var w = (k >= tabs.length - 1) ? (width - (bWidth * (tabs.length - 1))) : bWidth;
|
||||
b.resize(w, 24);
|
||||
b.x = x + (k * bWidth);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateBG() {
|
||||
bg.x = x;
|
||||
bg.y = y + 24;
|
||||
bg.resize(width, height - 24);
|
||||
}
|
||||
|
||||
public function switchTab(id:Int) {
|
||||
selectedTab = id;
|
||||
for(k=>b in tabButtons)
|
||||
b.disabled = k == selectedTab;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
bg.update(elapsed);
|
||||
for(e in tabButtons)
|
||||
e.update(elapsed);
|
||||
if (tabs[selectedTab] != null)
|
||||
tabs[selectedTab].update(elapsed);
|
||||
|
||||
if (DesktopMain.mouseInput.overlapsRect(bg, new FlxRect(x, y, width, height), camera))
|
||||
DesktopMain.mouseInput.cancel();
|
||||
}
|
||||
|
||||
public override function draw() {
|
||||
bg.draw();
|
||||
for(e in tabButtons)
|
||||
e.draw();
|
||||
if (tabs[selectedTab] != null)
|
||||
tabs[selectedTab].draw();
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package funkin.desktop.sprites;
|
||||
|
||||
import flixel.text.FlxText;
|
||||
import flixel.addons.ui.FlxUIText;
|
||||
import funkin.desktop.theme.Theme.ThemeData;
|
||||
|
||||
class WindowText extends FlxText {
|
||||
public function new(x:Float, y:Float, w:Float, t:String) {
|
||||
super(x, y, w, t);
|
||||
color = 0xFF000000;
|
||||
scrollFactor.set();
|
||||
size = 12;
|
||||
applyFontSettings(DesktopMain.theme.window);
|
||||
|
||||
scrollFactor.set();
|
||||
}
|
||||
|
||||
public function applyFontSettings(data:ThemeData) {
|
||||
if (data.font != null) {
|
||||
var fontPath:String;
|
||||
if (data.font.startsWith("file://")) {
|
||||
fontPath = data.font.substr(7);
|
||||
while(fontPath.charAt(0) == "/") fontPath = fontPath.substr(1);
|
||||
} else {
|
||||
fontPath = Paths.font(data.font);
|
||||
}
|
||||
font = fontPath;
|
||||
}
|
||||
if (data.fontSize != null)
|
||||
size = Std.int(data.fontSize);
|
||||
if (data.textColor != null)
|
||||
color = data.textColor;
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
package funkin.desktop.theme;
|
||||
|
||||
import flixel.util.FlxDestroyUtil.IFlxDestroyable;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.math.FlxPoint;
|
||||
import haxe.xml.Access;
|
||||
import openfl.Assets;
|
||||
|
||||
class Theme {
|
||||
public static function loadFromAssets(path:String) {
|
||||
return load(Assets.getText(path));
|
||||
}
|
||||
|
||||
public static function loadFromPath(path:String) {
|
||||
#if sys
|
||||
return load(sys.io.File.getContent(path));
|
||||
#else
|
||||
return null;
|
||||
#end
|
||||
}
|
||||
|
||||
public static function load(content:String):Theme {
|
||||
return new Theme(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* CAPTION & WINDOW
|
||||
*/
|
||||
public var window:ThemeData = new ThemeData();
|
||||
public var captionActive:ThemeData = new ThemeData();
|
||||
public var captionInactive:ThemeData = new ThemeData();
|
||||
public var captionButtons:ThemeData = new ThemeData();
|
||||
|
||||
/**
|
||||
* BUTTON
|
||||
*/
|
||||
public var normalButton:ThemeData = new ThemeData();
|
||||
public var hoverButton:ThemeData = new ThemeData();
|
||||
public var pressedButton:ThemeData = new ThemeData();
|
||||
public var disabledButton:ThemeData = new ThemeData();
|
||||
|
||||
/**
|
||||
* CHECKBOX
|
||||
*/
|
||||
public var checkbox:ThemeData = new ThemeData();
|
||||
|
||||
/**
|
||||
* TABS
|
||||
*/
|
||||
public var tabBackground:ThemeData = new ThemeData();
|
||||
public var tabButtonSelected:ThemeData = new ThemeData();
|
||||
public var tabButtonUnselected:ThemeData = new ThemeData();
|
||||
public var tabButtonHover:ThemeData = new ThemeData();
|
||||
public var tabButtonPressed:ThemeData = new ThemeData();
|
||||
|
||||
/**
|
||||
* CONTEXT MENU
|
||||
*/
|
||||
public var contextBackground:ThemeData = new ThemeData();
|
||||
public var contextOption:ThemeData = new ThemeData();
|
||||
|
||||
/**
|
||||
* MENU BAR
|
||||
*/
|
||||
public var menuBar:ThemeData = new ThemeData();
|
||||
|
||||
/**
|
||||
* THEME
|
||||
*/
|
||||
public var textbox:ThemeData = new ThemeData();
|
||||
public var textboxHover:ThemeData = new ThemeData();
|
||||
public var textboxPressed:ThemeData = new ThemeData();
|
||||
public var textboxFocused:ThemeData = new ThemeData();
|
||||
|
||||
public function new(content:String) {
|
||||
try {
|
||||
var access = new Access(Xml.parse(content).firstElement());
|
||||
var prefix = '';
|
||||
if (access.has.folder) prefix = access.att.folder.trim();
|
||||
for(element in access.elements) {
|
||||
var name:String = element.name.trim();
|
||||
if (!Type.getInstanceFields(Theme).contains(name)) continue;
|
||||
var field = Reflect.field(this, name);
|
||||
if (!(field is ThemeData)) continue;
|
||||
var data = cast(field, ThemeData);
|
||||
|
||||
if (element.has.path) data.sprite = '$prefix${element.att.path.trim()}';
|
||||
if (element.has.textColor) data.textColor = element.att.textColor.getColorFromDynamic();
|
||||
if (element.has.font) data.font = element.att.font;
|
||||
if (element.has.color) data.color = element.att.color.getColorFromDynamic();
|
||||
if (element.has.fontSize) data.fontSize = Std.parseFloat(element.att.fontSize).getDefault(0);
|
||||
if (element.has.left) data.left = Std.parseFloat(element.att.left).getDefault(0);
|
||||
if (element.has.right) data.right = Std.parseFloat(element.att.right).getDefault(0);
|
||||
if (element.has.top) data.top = Std.parseFloat(element.att.top).getDefault(0);
|
||||
if (element.has.bottom) data.bottom = Std.parseFloat(element.att.bottom).getDefault(0);
|
||||
if (element.has.width) data.width = Std.parseFloat(element.att.width).getDefault(data.width);
|
||||
if (element.has.height) data.height = Std.parseFloat(element.att.height).getDefault(data.height);
|
||||
if (element.has.size) {
|
||||
var split = element.att.size.split(",");
|
||||
data.size.set(
|
||||
Std.parseFloat(split[0]).getDefault(data.size.x),
|
||||
Std.parseFloat(split[1]).getDefault(data.size.y));
|
||||
}
|
||||
if (element.has.margin) {
|
||||
var split = element.att.margin.split(",");
|
||||
data.margin.set(
|
||||
Std.parseFloat(split[0]).getDefault(data.margin.x),
|
||||
Std.parseFloat(split[1]).getDefault(data.margin.y));
|
||||
}
|
||||
if (element.has.offset) {
|
||||
var split = element.att.offset.split(",");
|
||||
data.offset.set(
|
||||
Std.parseFloat(split[0]).getDefault(data.offset.x),
|
||||
Std.parseFloat(split[1]).getDefault(data.offset.y));
|
||||
}
|
||||
|
||||
}
|
||||
} catch(e) {
|
||||
Logs.trace('Failed to load Desktop Theme: $e', ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ThemeData implements IFlxDestroyable {
|
||||
public var sprite:String = "";
|
||||
|
||||
public var font:String = null;
|
||||
public var fontSize:Null<Float> = null;
|
||||
|
||||
public var textColor:Null<FlxColor> = null;
|
||||
public var color:FlxColor = FlxColor.WHITE;
|
||||
|
||||
public var left:Float = 4;
|
||||
public var bottom:Float = 4;
|
||||
public var top:Float = 4;
|
||||
public var right:Float = 4;
|
||||
|
||||
public var width:Float = 4;
|
||||
public var height:Float = 4;
|
||||
|
||||
public var margin:FlxPoint = FlxPoint.get(0, 0);
|
||||
public var size:FlxPoint = FlxPoint.get(20, 20);
|
||||
public var offset:FlxPoint = FlxPoint.get(5, 5);
|
||||
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function destroy() {
|
||||
if (margin != null)
|
||||
margin.put();
|
||||
if (size != null)
|
||||
size.put();
|
||||
if (offset != null)
|
||||
offset.put();
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package funkin.desktop.windows;
|
||||
|
||||
import flixel.util.FlxDestroyUtil;
|
||||
import funkin.desktop.sprites.*;
|
||||
|
||||
class ContextMenu extends WindowGroup<FlxObject> {
|
||||
public var bg:SpliceSprite;
|
||||
public var texts:Array<WindowText> = [];
|
||||
public var selectionBGs:Array<FlxSprite> = [];
|
||||
public var callback:Int->Void;
|
||||
public var contextOptions:Array<ContextOption> = [];
|
||||
public var contextCamera:FlxCamera;
|
||||
|
||||
public override function new(x:Float, y:Float, options:Array<ContextOption>, callback:Int->Void) {
|
||||
super();
|
||||
this.callback = callback;
|
||||
this.contextOptions = options;
|
||||
|
||||
var bgTheme = DesktopMain.theme.contextBackground;
|
||||
var optionTheme = DesktopMain.theme.contextOption;
|
||||
|
||||
bg = new SpliceSprite(Paths.image(bgTheme.sprite), 0, 0, 75, 24, bgTheme.left, bgTheme.top, bgTheme.bottom, bgTheme.right);
|
||||
add(bg);
|
||||
|
||||
var lastOption:FlxSprite = null;
|
||||
var w:Float = 80;
|
||||
for(k=>o in options) {
|
||||
var selectSpr = new FlxSprite(bgTheme.left, bgTheme.top + (k * optionTheme.height));
|
||||
selectSpr.loadGraphic(Paths.image(optionTheme.sprite));
|
||||
selectSpr.setGraphicSize(10, Std.int(optionTheme.height));
|
||||
selectSpr.visible = false;
|
||||
selectionBGs.push(selectSpr);
|
||||
add(selectSpr);
|
||||
|
||||
var text = new WindowText(4, 4, 0, o.name);
|
||||
text.y = selectSpr.y + ((selectSpr.height - text.height) / 2);
|
||||
text.applyFontSettings(bgTheme);
|
||||
texts.push(text);
|
||||
add(text);
|
||||
if (w < text.width)
|
||||
w = text.width;
|
||||
|
||||
lastOption = selectSpr;
|
||||
}
|
||||
var ow = Std.int(w) + 20;
|
||||
for(o in selectionBGs) {
|
||||
o.setGraphicSize(ow, Std.int(optionTheme.height));
|
||||
o.updateHitbox();
|
||||
}
|
||||
bg.resize(bgTheme.left + ow + bgTheme.right, lastOption.y + lastOption.height + bgTheme.bottom);
|
||||
contextCamera = camera = new FlxCamera(Std.int(x), Std.int(y), Std.int(bg.width), Std.int(bg.height));
|
||||
contextCamera.pixelPerfectRender = true;
|
||||
contextCamera.bgColor = 0;
|
||||
FlxG.cameras.add(contextCamera, false);
|
||||
}
|
||||
|
||||
public static function open(x:Float, y:Float, options:Array<ContextOption>, callback:Int->Void) {
|
||||
DesktopMain.contextMenu = new ContextMenu(x, y, options, callback);
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
if (DesktopMain.mouseInput.overlaps(bg, contextCamera)) {
|
||||
for(i=>o in selectionBGs) {
|
||||
var wasVisible = o.visible;
|
||||
if (o.visible = DesktopMain.mouseInput.overlaps(o, contextCamera)) {
|
||||
if (DesktopMain.mouseInput.justReleased) {
|
||||
// select option
|
||||
if (contextOptions[i].callback != null)
|
||||
contextOptions[i].callback();
|
||||
if (callback != null)
|
||||
callback(i);
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (o.visible != wasVisible) {
|
||||
texts[i].applyFontSettings(o.visible ? DesktopMain.theme.contextOption : DesktopMain.theme.contextBackground);
|
||||
}
|
||||
}
|
||||
DesktopMain.mouseInput.cancel();
|
||||
} else {
|
||||
if (DesktopMain.mouseInput.justPressed) {
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override function destroy() {
|
||||
FlxG.cameras.remove(contextCamera, true);
|
||||
DesktopMain.contextMenu = null;
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
typedef ContextOption = {
|
||||
var name:String;
|
||||
@:optional var callback:Void->Void;
|
||||
@:optional var iconPath:String;
|
||||
@:optional var iconId:Int;
|
||||
}
|
||||
@@ -1,297 +0,0 @@
|
||||
package funkin.desktop.windows;
|
||||
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.addons.ui.FlxUIText;
|
||||
import openfl.geom.Point;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import openfl.geom.Rectangle;
|
||||
import flixel.addons.ui.FlxUI9SliceSprite;
|
||||
import flixel.tweens.FlxTween;
|
||||
import funkin.desktop.sprites.*;
|
||||
import funkin.desktop.editors.MessageBox.MessageBoxIcon;
|
||||
import funkin.desktop.editors.MessageBox;
|
||||
|
||||
|
||||
typedef WindowCam = {
|
||||
var camera:FlxCamera;
|
||||
var resizeScroll:Bool;
|
||||
var width:Int;
|
||||
var height:Int;
|
||||
}
|
||||
class Window extends FlxTypedGroup<FlxBasic> {
|
||||
public var windowFrame:SpliceSprite;
|
||||
public var windowInactiveFrame:SpliceSprite;
|
||||
public var captionButtons:FlxTypedSpriteGroup<WindowCaptionButton>;
|
||||
|
||||
public var windowWidth:Int = 0;
|
||||
public var windowHeight:Int = 0;
|
||||
|
||||
public var windowCaptionCamera:FlxCamera;
|
||||
public var windowCameras:Array<WindowCam> = [];
|
||||
|
||||
private var __captionTweens:Array<FlxTween> = [];
|
||||
private var __closing:Bool = false;
|
||||
|
||||
public var content:WindowContent;
|
||||
|
||||
public var caption:WindowText;
|
||||
public var icon:FlxSprite;
|
||||
public var dragHitbox:WindowDragHitbox;
|
||||
|
||||
public var moveable:Bool = true;
|
||||
public var resizeable:Bool = true;
|
||||
public var canClose:Bool = true;
|
||||
public var canMinimize:Bool = true;
|
||||
public var canHelp:Bool = false;
|
||||
|
||||
public var maximized:Bool = false;
|
||||
|
||||
public var focused(get, null):Bool;
|
||||
|
||||
public var curDialog:Window = null;
|
||||
|
||||
public function openDialog(window:Window) {
|
||||
curDialog = window;
|
||||
if (focused) DesktopMain.instance.focusWindow(curDialog);
|
||||
}
|
||||
private function get_focused() {
|
||||
return DesktopMain.instance.windows.members.last() == this;
|
||||
}
|
||||
|
||||
public function showMessage(caption:String, message:String, icon:MessageBoxIcon) {
|
||||
var win = DesktopMain.instance.openWindow(new MessageBox(caption, message, icon));
|
||||
curDialog = win;
|
||||
win.move(
|
||||
windowCaptionCamera.x + ((windowCaptionCamera.width - win.windowCaptionCamera.width) / 2),
|
||||
windowCaptionCamera.y + ((windowCaptionCamera.height - win.windowCaptionCamera.height) / 2));
|
||||
}
|
||||
|
||||
public function loadIcon(path:String) {
|
||||
icon.loadGraphic(path);
|
||||
icon.setUnstretchedGraphicSize(16, 16, false);
|
||||
}
|
||||
public function new(content:WindowContent) {
|
||||
super();
|
||||
windowFrame = new SpliceSprite(Paths.image(DesktopMain.theme.captionActive.sprite), 0, 0, 10, 10,
|
||||
Std.int(DesktopMain.theme.captionActive.left),
|
||||
Std.int(DesktopMain.theme.captionActive.top),
|
||||
Std.int(DesktopMain.theme.captionActive.right),
|
||||
Std.int(DesktopMain.theme.captionActive.bottom));
|
||||
windowInactiveFrame = new SpliceSprite(Paths.image(DesktopMain.theme.captionInactive.sprite), 0, 0, 10, 10,
|
||||
Std.int(DesktopMain.theme.captionInactive.left),
|
||||
Std.int(DesktopMain.theme.captionInactive.top),
|
||||
Std.int(DesktopMain.theme.captionInactive.right),
|
||||
Std.int(DesktopMain.theme.captionInactive.bottom));
|
||||
add(windowFrame);
|
||||
add(windowInactiveFrame);
|
||||
|
||||
caption = new WindowText(24, 4, 0, content.title);
|
||||
caption.applyFontSettings(DesktopMain.theme.captionActive);
|
||||
caption.borderSize = 1.25;
|
||||
caption.borderStyle = OUTLINE;
|
||||
caption.borderColor = 0x63000000;
|
||||
|
||||
captionButtons = new FlxTypedSpriteGroup<WindowCaptionButton>();
|
||||
for(i in 0...4) {
|
||||
var btn = new WindowCaptionButton(this, i);
|
||||
btn.x = (i+1) * -(DesktopMain.theme.captionButtons.size.x + DesktopMain.theme.captionButtons.margin.x);
|
||||
captionButtons.add(btn);
|
||||
}
|
||||
|
||||
caption.y = (DesktopMain.theme.captionActive.top - caption.height) / 2;
|
||||
add(caption);
|
||||
|
||||
dragHitbox = new WindowDragHitbox(DesktopMain.theme.captionActive.left, DesktopMain.theme.captionActive.left, DesktopMain.theme.captionActive.left, DesktopMain.theme.captionActive.top);
|
||||
dragHitbox.parent = this;
|
||||
add(dragHitbox);
|
||||
|
||||
icon = new FlxSprite(4, (DesktopMain.theme.captionActive.top - 16) / 2);
|
||||
add(icon);
|
||||
loadIcon(content.icon);
|
||||
|
||||
add(captionButtons);
|
||||
|
||||
this.content = content;
|
||||
|
||||
// scrollFactor.set(0.5, 0.5);
|
||||
|
||||
windowCaptionCamera = new FlxCamera(0, 0, content.width, content.height, 1);
|
||||
windowCaptionCamera.pixelPerfectRender = true;
|
||||
windowCaptionCamera.bgColor = 0;
|
||||
FlxG.cameras.add(windowCaptionCamera, false);
|
||||
cameras = [windowCaptionCamera];
|
||||
dragHitbox.cameras = [windowCaptionCamera];
|
||||
|
||||
for(btn in captionButtons.members)
|
||||
btn.cameras = cameras; // so that buttons detects on the right camera
|
||||
|
||||
if (content.windowCamera == null) {
|
||||
content.windowCamera = new FlxCamera(Std.int(content.winX + 4), Std.int(content.winY + 23), Std.int(content.width), Std.int(content.height), 1);
|
||||
content.windowCamera.pixelPerfectRender = true;
|
||||
content.windowCamera.bgColor = DesktopMain.theme.window.color;
|
||||
}
|
||||
content.cameras = [content.windowCamera];
|
||||
content.parent = this;
|
||||
addCamera(content.windowCamera);
|
||||
content.create();
|
||||
add(content);
|
||||
|
||||
windowWidth = content.width;
|
||||
windowHeight = content.height;
|
||||
|
||||
popupCamera(windowCaptionCamera);
|
||||
for(e in windowCameras) popupCamera(e.camera);
|
||||
|
||||
resize(content.width, content.height);
|
||||
move(content.winX, content.winY);
|
||||
}
|
||||
|
||||
public function addCamera(camera:FlxCamera, useResizeTechnique:Bool = true) {
|
||||
FlxG.cameras.add(camera, false);
|
||||
windowCameras.push({
|
||||
camera: camera,
|
||||
resizeScroll: useResizeTechnique,
|
||||
width: camera.width,
|
||||
height: camera.height
|
||||
});
|
||||
}
|
||||
|
||||
public function onDesktopSizeChange(width:Int, height:Int) {
|
||||
if (maximized) {
|
||||
resize(width, Std.int(height - DesktopMain.theme.captionActive.top + DesktopMain.theme.captionActive.left));
|
||||
}
|
||||
content.onDesktopSizeChange(width, height);
|
||||
}
|
||||
|
||||
public function maximize() {
|
||||
if (maximized != (maximized = true)) {
|
||||
// maximizing!!
|
||||
captionButtons.members[1].animation.play("restore", true);
|
||||
move(-DesktopMain.theme.captionActive.left, -DesktopMain.theme.captionActive.left);
|
||||
resize(FlxG.width, Std.int(FlxG.height - DesktopMain.theme.captionActive.top + DesktopMain.theme.captionActive.left)); // TODO: taskbar stuff
|
||||
}
|
||||
}
|
||||
|
||||
public function minimize() {
|
||||
|
||||
}
|
||||
|
||||
public function restore() {
|
||||
if (maximized != (maximized = false)) {
|
||||
// maximizing!!
|
||||
captionButtons.members[1].animation.play("maximize", true);
|
||||
move(100, 100);
|
||||
var w:Int = 320;
|
||||
var h:Int = 320;
|
||||
if (windowCameras[0] != null) {
|
||||
w = windowCameras[0].width;
|
||||
h = windowCameras[0].height;
|
||||
}
|
||||
resize(w, h); // TODO: taskbar stuff
|
||||
}
|
||||
}
|
||||
|
||||
public function changeCaption(text:String) {
|
||||
caption.text = text;
|
||||
}
|
||||
|
||||
public function popupCamera(cam:FlxCamera, popout:Bool = false, ?onFinish:FlxTween->Void) {
|
||||
if (popout) {
|
||||
__captionTweens.push(FlxTween.tween(cam.flashSprite, {scaleX: 0.85, scaleY: 0.85}, 1/5, {ease: FlxEase.quintOut}));
|
||||
__captionTweens.push(FlxTween.tween(cam, {alpha: 0}, 1/5, {ease: FlxEase.quintOut, onComplete: onFinish}));
|
||||
} else {
|
||||
cam.flashSprite.scaleX = 0.85;
|
||||
cam.flashSprite.scaleY = 0.85;
|
||||
cam.alpha = 0;
|
||||
|
||||
__captionTweens.push(FlxTween.tween(cam.flashSprite, {scaleX: 1, scaleY: 1}, 1/3, {ease: FlxEase.cubeOut}));
|
||||
__captionTweens.push(FlxTween.tween(cam, {alpha: 1}, 1/3, {ease: FlxEase.cubeOut, onComplete: onFinish}));
|
||||
}
|
||||
}
|
||||
public override function destroy() {
|
||||
super.destroy();
|
||||
for(e in __captionTweens) e.cancel();
|
||||
FlxG.cameras.remove(windowCaptionCamera, true);
|
||||
for(cam in windowCameras) {
|
||||
FlxG.cameras.remove(cam.camera, true);
|
||||
}
|
||||
windowCameras = null;
|
||||
windowCaptionCamera = null;
|
||||
__captionTweens = null;
|
||||
}
|
||||
|
||||
public function resize(width:Int, height:Int) {
|
||||
windowWidth = width;
|
||||
windowHeight = height;
|
||||
updateWindowFrame();
|
||||
}
|
||||
|
||||
public function move(x:Float, y:Float) {
|
||||
@:privateAccess content.__noParentUpdate = true;
|
||||
content.winX = windowCaptionCamera.x = x;
|
||||
content.winY = windowCaptionCamera.y = y;
|
||||
@:privateAccess content.__noParentUpdate = false;
|
||||
for(e in windowCameras) {
|
||||
e.camera.x = x + Std.int(DesktopMain.theme.captionActive.left);
|
||||
e.camera.y = y + Std.int(DesktopMain.theme.captionActive.top);
|
||||
}
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
if (__closing) {
|
||||
// DesktopMain.instance.windows.remove(this, true);
|
||||
// destroy();
|
||||
return;
|
||||
}
|
||||
windowInactiveFrame.visible = !(windowFrame.visible = focused);
|
||||
var i = members.length;
|
||||
|
||||
var shouldCancel = DesktopMain.mouseInput.overlapsRect(this, new FlxRect(0, 0, windowCaptionCamera.width, windowCaptionCamera.height), windowCaptionCamera);
|
||||
|
||||
|
||||
|
||||
if (curDialog != null && curDialog.exists) {
|
||||
if (shouldCancel) {
|
||||
if (DesktopMain.mouseInput.justPressed) {
|
||||
// TODO: sounds
|
||||
DesktopMain.instance.focusWindow(curDialog);
|
||||
}
|
||||
DesktopMain.mouseInput.cancel();
|
||||
}
|
||||
return;
|
||||
} else if (shouldCancel && DesktopMain.mouseInput.justPressed)
|
||||
DesktopMain.instance.focusWindow(this);
|
||||
// updates them backwards!!
|
||||
while(i > 0) {
|
||||
i--;
|
||||
var spr = members[i];
|
||||
if (spr == null || !spr.exists) continue;
|
||||
spr.update(elapsed);
|
||||
}
|
||||
|
||||
if (shouldCancel) DesktopMain.mouseInput.cancel();
|
||||
}
|
||||
|
||||
public function close() {
|
||||
__closing = true;
|
||||
popupCamera(windowCaptionCamera, true, function(t) {
|
||||
DesktopMain.instance.windows.remove(this, true);
|
||||
destroy();
|
||||
});
|
||||
for(e in windowCameras) popupCamera(e.camera, true);
|
||||
}
|
||||
|
||||
public function updateWindowFrame() {
|
||||
for(frame in [windowInactiveFrame, windowFrame])
|
||||
frame.resize(windowWidth + Std.int(DesktopMain.theme.captionActive.left * 2), windowHeight + Std.int(DesktopMain.theme.captionActive.top) + Std.int(DesktopMain.theme.captionActive.left));
|
||||
windowCaptionCamera.setSize(windowWidth + Std.int(DesktopMain.theme.captionActive.left * 2), windowHeight + Std.int(DesktopMain.theme.captionActive.top) + Std.int(DesktopMain.theme.captionActive.left));
|
||||
captionButtons.setPosition(windowWidth + Std.int((DesktopMain.theme.captionActive.left * 2) - DesktopMain.theme.captionButtons.offset.x), Std.int(DesktopMain.theme.captionButtons.offset.y));
|
||||
for(e in windowCameras) {
|
||||
e.camera.setSize(windowWidth, windowHeight);
|
||||
if (e.resizeScroll) {
|
||||
e.camera.scroll.set(-Std.int(e.camera.width - e.width), -Std.int(e.camera.height - e.height));
|
||||
}
|
||||
}
|
||||
content.onWindowResize(windowWidth, windowHeight);
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package funkin.desktop.windows;
|
||||
|
||||
|
||||
class WindowCaptionButton extends FlxSprite {
|
||||
public var icon:FlxSprite;
|
||||
public var window:Window;
|
||||
|
||||
public static var anims:Array<String> = ["close", "maximize", "minimize", "help", "restore"];
|
||||
|
||||
public function new(window:Window, i:Int) {
|
||||
super(0, 0);
|
||||
this.window = window;
|
||||
ID = i;
|
||||
|
||||
loadGraphic(Paths.image(DesktopMain.theme.captionButtons.sprite), true, Std.int(DesktopMain.theme.captionButtons.size.x), Std.int(DesktopMain.theme.captionButtons.size.y));
|
||||
|
||||
for(k=>e in anims) {
|
||||
animation.add(e, [for(l in 0...8) k + (l * anims.length)], 0, true);
|
||||
}
|
||||
animation.play(anims[ID]);
|
||||
}
|
||||
|
||||
public override function draw() {
|
||||
super.draw();
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
if (animation.curAnim == null) {
|
||||
super.update(elapsed);
|
||||
return;
|
||||
}
|
||||
var mouseInput = DesktopMain.mouseInput;
|
||||
|
||||
visible = switch(ID) {
|
||||
case 1 | 2: window.resizeable || window.canMinimize;
|
||||
case 3: window.canHelp;
|
||||
default: true;
|
||||
};
|
||||
|
||||
if(switch(ID) {
|
||||
case 0: window.canClose;
|
||||
case 1: window.resizeable;
|
||||
case 2: window.canMinimize;
|
||||
case 3: window.canHelp;
|
||||
default: true;
|
||||
}) {
|
||||
if (DesktopMain.mouseInput.overlaps(this, camera)) {
|
||||
if (mouseInput.justReleased) {
|
||||
switch(ID) {
|
||||
case 0:
|
||||
if (window.canClose) window.close();
|
||||
case 1:
|
||||
if (window.resizeable) (window.maximized ? window.restore : window.maximize)();
|
||||
case 2:
|
||||
if (window.canMinimize) window.minimize();
|
||||
}
|
||||
mouseInput.cancel();
|
||||
return;
|
||||
}
|
||||
if (mouseInput.pressed || mouseInput.justPressed) {
|
||||
animation.curAnim.curFrame = 2;
|
||||
} else {
|
||||
animation.curAnim.curFrame = 1;
|
||||
}
|
||||
mouseInput.cancel(); // prevents controls behind this one from updating input
|
||||
} else
|
||||
animation.curAnim.curFrame = 0;
|
||||
} else {
|
||||
animation.curAnim.curFrame = 3;
|
||||
}
|
||||
if (!window.focused) animation.curAnim.curFrame += 4;
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package funkin.desktop.windows;
|
||||
|
||||
|
||||
class WindowContent extends WindowGroup<FlxBasic> {
|
||||
public var winX(default, set):Float = 0;
|
||||
public var winY(default, set):Float = 0;
|
||||
public var title(default, set):String = "Window";
|
||||
public var icon(default, set):String = 'flixel/images/logo/default.png';
|
||||
|
||||
public var windowCamera:FlxCamera = null;
|
||||
public var parent:Window = null;
|
||||
|
||||
public var width(default, set):Int = 0;
|
||||
public var height(default, set):Int = 0;
|
||||
|
||||
private var __noParentUpdate:Bool = false;
|
||||
private function set_width(w:Int):Int {
|
||||
width = w;
|
||||
if (parent != null && !__noParentUpdate) {
|
||||
parent.windowWidth = w;
|
||||
if (!__noParentUpdate)
|
||||
parent.updateWindowFrame();
|
||||
}
|
||||
return width;
|
||||
}
|
||||
private function set_height(h:Int):Int {
|
||||
height = h;
|
||||
if (parent != null && !__noParentUpdate) {
|
||||
parent.windowHeight = h;
|
||||
if (!__noParentUpdate)
|
||||
parent.updateWindowFrame();
|
||||
}
|
||||
return height;
|
||||
}
|
||||
private function set_winX(v:Float):Float {
|
||||
winX = v;
|
||||
if (parent != null && !__noParentUpdate) parent.move(winX, winY);
|
||||
return winX;
|
||||
}
|
||||
|
||||
private function set_title(text:String):String {
|
||||
title = text;
|
||||
if (parent != null && !__noParentUpdate) parent.changeCaption(title);
|
||||
return title;
|
||||
}
|
||||
|
||||
private function set_icon(text:String):String {
|
||||
icon = text;
|
||||
if (parent != null && !__noParentUpdate) parent.loadIcon(icon);
|
||||
return icon;
|
||||
}
|
||||
private function set_winY(v:Float):Float {
|
||||
winY = v;
|
||||
if (parent != null && !__noParentUpdate) parent.move(winX, winY);
|
||||
return winY;
|
||||
}
|
||||
|
||||
public function setSize(width:Int, height:Int) {
|
||||
__noParentUpdate = true;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
__noParentUpdate = false;
|
||||
if (parent != null) parent.updateWindowFrame();
|
||||
}
|
||||
|
||||
public function new(caption:String, x:Float, y:Float, width:Int, height:Int) {
|
||||
super();
|
||||
this.title = caption;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.winX = x;
|
||||
this.winY = y;
|
||||
this.updateScrolls = false;
|
||||
}
|
||||
|
||||
public function create() {
|
||||
|
||||
}
|
||||
|
||||
public function onWindowResize(width:Int, height:Int) {
|
||||
|
||||
}
|
||||
|
||||
public function onDesktopSizeChange(width:Int, height:Int) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package funkin.desktop.windows;
|
||||
|
||||
import flixel.math.FlxPoint;
|
||||
|
||||
class WindowDragHitbox extends FlxObject {
|
||||
public var parent:Window;
|
||||
|
||||
public var left:Float;
|
||||
public var top:Float;
|
||||
public var right:Float;
|
||||
|
||||
public var dragging:Bool = false;
|
||||
|
||||
public var offset:FlxPoint;
|
||||
|
||||
public function new(left:Float, top:Float, right:Float, height:Float) {
|
||||
super();
|
||||
x = left;
|
||||
y = top;
|
||||
this.left = left;
|
||||
this.top = top;
|
||||
this.right = right;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public override function get_width() {
|
||||
return parent.windowCaptionCamera.width - left - right;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
if (!parent.moveable || parent.maximized) {
|
||||
dragging = false;
|
||||
return;
|
||||
}
|
||||
if (dragging) {
|
||||
var screenPos = FlxG.mouse.getScreenPosition(FlxG.camera);
|
||||
screenPos.x = FlxMath.bound(screenPos.x, 0, FlxG.camera.width);
|
||||
screenPos.y = FlxMath.bound(screenPos.y, 0, FlxG.camera.height);
|
||||
|
||||
if (DesktopMain.mouseInput.justReleased) {
|
||||
dragging = false;
|
||||
offset.put();
|
||||
return;
|
||||
}
|
||||
parent.move(screenPos.x + offset.x, screenPos.y + offset.y);
|
||||
DesktopMain.mouseInput.cancel();
|
||||
} else {
|
||||
if (DesktopMain.mouseInput.overlaps(this, camera)) {
|
||||
if (DesktopMain.mouseInput.justPressed) {
|
||||
var screenPos = FlxG.mouse.getScreenPosition(FlxG.camera);
|
||||
offset = FlxPoint.get(parent.content.winX - screenPos.x, parent.content.winY - screenPos.y);
|
||||
dragging = true;
|
||||
} else if (DesktopMain.mouseInput.justPressedRight) {
|
||||
var input = DesktopMain.mouseInput;
|
||||
ContextMenu.open(input.screenPos.x, input.screenPos.y, [
|
||||
{
|
||||
name: "Close",
|
||||
callback: function() {
|
||||
parent.close();
|
||||
}
|
||||
}
|
||||
], function(i) {
|
||||
trace(i);
|
||||
});
|
||||
}
|
||||
DesktopMain.mouseInput.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override function destroy() {
|
||||
super.destroy();
|
||||
if (offset != null)
|
||||
offset.put();
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package funkin.desktop.windows;
|
||||
|
||||
import flixel.math.FlxPoint;
|
||||
|
||||
class WindowGroup<T:FlxBasic> extends FlxTypedGroup<T> {
|
||||
public var x:Float = 0;
|
||||
public var y:Float = 0;
|
||||
public var scrollFactor:FlxPoint = FlxPoint.get(0, 0);
|
||||
public var updateScrolls:Bool = true;
|
||||
|
||||
public override function add(obj:T) {
|
||||
super.add(obj);
|
||||
|
||||
if (!updateScrolls) return obj;
|
||||
if (obj is FlxObject) {
|
||||
var o = cast(obj, FlxObject);
|
||||
o.x += x;
|
||||
o.y += y;
|
||||
} else if (obj is WindowGroup) {
|
||||
var o:WindowGroup<FlxBasic> = cast obj;
|
||||
o.x += x;
|
||||
o.y += y;
|
||||
}
|
||||
__updateObjScrollFactor(obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function updateAnchor(x:Float, y:Float, ?cameras:Array<FlxCamera>) {
|
||||
scrollFactor.set(x, y);
|
||||
if (cameras != null) this.cameras = cameras;
|
||||
if (!updateScrolls) return;
|
||||
for(obj in members)
|
||||
__updateObjScrollFactor(obj, cameras);
|
||||
}
|
||||
|
||||
private function __updateObjScrollFactor(obj:FlxBasic, ?cameras:Array<FlxCamera>) {
|
||||
if (obj is FlxObject) {
|
||||
var o = cast(obj, FlxObject);
|
||||
if (cameras != null) o.cameras = cameras;
|
||||
o.scrollFactor.set(scrollFactor.x, scrollFactor.y);
|
||||
} else if (obj is WindowGroup) {
|
||||
var o:WindowGroup<FlxBasic> = cast obj;
|
||||
o.updateAnchor(scrollFactor.x, scrollFactor.y, cameras);
|
||||
}
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
// update them backwards, so that the top most window gets the priority
|
||||
var i = length;
|
||||
|
||||
@:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras;
|
||||
@:privateAccess if (cameras != null) FlxCamera._defaultCameras = cameras;
|
||||
|
||||
while(i > 0) {
|
||||
i--;
|
||||
var window = members[i];
|
||||
if (window == null || !window.exists)
|
||||
continue;
|
||||
window.update(elapsed);
|
||||
}
|
||||
|
||||
@:privateAccess FlxCamera._defaultCameras = oldDefaultCameras;
|
||||
}
|
||||
|
||||
public override function destroy() {
|
||||
super.destroy();
|
||||
scrollFactor.put();
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,11 @@ class EditorPicker extends MusicBeatSubstate {
|
||||
iconID: 2,
|
||||
state: null
|
||||
},
|
||||
{
|
||||
name: "UI Debug State",
|
||||
iconID: 3,
|
||||
state: UIDebugState
|
||||
},
|
||||
{
|
||||
name: "Debug Options",
|
||||
iconID: 4,
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package funkin.editors;
|
||||
|
||||
import funkin.editors.ui.*;
|
||||
|
||||
class UIDebugState extends UIState {
|
||||
public override function create() {
|
||||
super.create();
|
||||
add(new UICheckbox(10, 10, "Test unchecked", false));
|
||||
add(new UICheckbox(10, 40, "Test checked", true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package funkin.editors.charter;
|
||||
|
||||
class Charter extends MusicBeatState {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package funkin.editors.ui;
|
||||
|
||||
import funkin.ui.FunkinText;
|
||||
|
||||
class UICheckbox extends UISprite {
|
||||
public var field:FunkinText;
|
||||
public var check:FlxSprite;
|
||||
|
||||
public var checked:Bool = false;
|
||||
|
||||
var hovered:Bool = false;
|
||||
var pressed:Bool = 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;
|
||||
|
||||
field = new FunkinText(x, y, text, w);
|
||||
check = new FlxSprite().loadGraphicFromSprite(this);
|
||||
check.animation.play("checkmark");
|
||||
|
||||
members.push(check);
|
||||
members.push(field);
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
// ANIMATION HANDLING
|
||||
animation.play(hovered ? (pressed ? "pressed" : "hover") : "normal");
|
||||
hovered = false;
|
||||
pressed = false;
|
||||
|
||||
// CHECKMARK HANDLING
|
||||
check.visible = checked;
|
||||
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();
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
public inline function updatePositions() {
|
||||
field.setPosition(x + 30, y);
|
||||
check.setPosition(x, y);
|
||||
}
|
||||
|
||||
public override function draw() {
|
||||
updatePositions();
|
||||
super.draw();
|
||||
}
|
||||
|
||||
public override function onHovered() {
|
||||
hovered = true;
|
||||
if (FlxG.mouse.pressed)
|
||||
pressed = true;
|
||||
if (FlxG.mouse.justReleased) {
|
||||
// clicked
|
||||
checked = !checked;
|
||||
check.scale.set(1.25, 1.25);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package funkin.editors.ui;
|
||||
|
||||
import flixel.util.FlxDestroyUtil;
|
||||
import flixel.math.FlxRect;
|
||||
|
||||
@:allow(funkin.editors.ui.UIState)
|
||||
class UISprite extends FlxSprite {
|
||||
public var members:Array<FlxBasic> = [];
|
||||
|
||||
private var __lastDrawCameras:Array<FlxCamera> = [];
|
||||
private var __rect:FlxRect = new FlxRect();
|
||||
|
||||
private var __oldDefCams:Array<FlxCamera>;
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
updateButton();
|
||||
|
||||
@:privateAccess {
|
||||
__oldDefCams = FlxCamera._defaultCameras;
|
||||
FlxCamera._defaultCameras = cameras;
|
||||
|
||||
for(m in members)
|
||||
m.update(elapsed);
|
||||
|
||||
FlxCamera._defaultCameras = __oldDefCams;
|
||||
}
|
||||
}
|
||||
|
||||
public override function draw() {
|
||||
super.draw();
|
||||
|
||||
@:privateAccess {
|
||||
__oldDefCams = FlxCamera._defaultCameras;
|
||||
FlxCamera._defaultCameras = cameras;
|
||||
|
||||
for(m in members)
|
||||
m.draw();
|
||||
|
||||
FlxCamera._defaultCameras = __oldDefCams;
|
||||
}
|
||||
__lastDrawCameras = [for(c in cameras) c];
|
||||
}
|
||||
|
||||
|
||||
public override function destroy() {
|
||||
super.destroy();
|
||||
members = FlxDestroyUtil.destroyArray(members);
|
||||
}
|
||||
|
||||
public function updateButton() {
|
||||
UIState.state.updateButtonHandler(this, onHovered);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever the sprite is being hovered by the mouse.
|
||||
*/
|
||||
public function onHovered() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package funkin.editors.ui;
|
||||
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.math.FlxRect;
|
||||
|
||||
class UIState extends MusicBeatState {
|
||||
public static var state(get, null):UIState;
|
||||
|
||||
public var buttonHandler:Void->Void = null;
|
||||
|
||||
private var __rect:FlxRect;
|
||||
private var __mousePos:FlxPoint;
|
||||
|
||||
private inline static function get_state()
|
||||
return FlxG.state is UIState ? cast FlxG.state : null;
|
||||
|
||||
public override function create() {
|
||||
__rect = new FlxRect();
|
||||
__mousePos = FlxPoint.get();
|
||||
super.create();
|
||||
}
|
||||
|
||||
public function updateButtonHandler(spr:UISprite, buttonHandler:Void->Void) {
|
||||
spr.__rect.x = spr.x;
|
||||
spr.__rect.y = spr.y;
|
||||
spr.__rect.width = spr.width;
|
||||
spr.__rect.height = spr.height;
|
||||
updateRectButtonHandler(spr, spr.__rect, buttonHandler);
|
||||
}
|
||||
|
||||
|
||||
public function updateRectButtonHandler(spr:UISprite, rect:FlxRect, buttonHandler:Void->Void) {
|
||||
var pos = FlxG.mouse.getScreenPosition(camera);
|
||||
for(camera in spr.__lastDrawCameras) {
|
||||
__rect.x = rect.x;
|
||||
__rect.y = rect.y;
|
||||
__rect.width = rect.width;
|
||||
__rect.height = rect.height;
|
||||
|
||||
__rect.x -= camera.scroll.x * spr.scrollFactor.x;
|
||||
__rect.y -= camera.scroll.y * spr.scrollFactor.y;
|
||||
|
||||
if (((pos.x > __rect.x) && (pos.x < __rect.x + rect.width)) && ((pos.y > __rect.y) && (pos.y < __rect.y + __rect.height))) {
|
||||
this.buttonHandler = buttonHandler;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
|
||||
if (buttonHandler != null) {
|
||||
buttonHandler();
|
||||
buttonHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override function destroy() {
|
||||
super.destroy();
|
||||
__mousePos.put();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package funkin.system;
|
||||
|
||||
import funkin.desktop.DesktopMain;
|
||||
import openfl.utils.AssetLibrary;
|
||||
import openfl.utils.AssetCache;
|
||||
import openfl.text.TextFormat;
|
||||
@@ -156,7 +155,6 @@ class Main extends Sprite
|
||||
Logs.init();
|
||||
Paths.init();
|
||||
ModsFolder.init();
|
||||
DesktopMain.init();
|
||||
DiscordUtil.init();
|
||||
#if GLOBAL_SCRIPT
|
||||
funkin.scripting.GlobalScript.init();
|
||||
|
||||