diff --git a/assets/images/desktop/ui.xml b/assets/images/desktop/ui.xml
index 66b00bf6..4b2aac16 100644
--- a/assets/images/desktop/ui.xml
+++ b/assets/images/desktop/ui.xml
@@ -1,5 +1,8 @@
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/images/desktop/ui/caption.png b/assets/images/desktop/ui/caption.png
index c981a604..01cff8f6 100644
Binary files a/assets/images/desktop/ui/caption.png and b/assets/images/desktop/ui/caption.png differ
diff --git a/assets/images/desktop/ui/captionButtons.png b/assets/images/desktop/ui/captionButtons.png
index faadfa29..c0e1caef 100644
Binary files a/assets/images/desktop/ui/captionButtons.png and b/assets/images/desktop/ui/captionButtons.png differ
diff --git a/assets/images/desktop/ui/captionInactive.png b/assets/images/desktop/ui/captionInactive.png
index 6e562221..14f9d1d7 100644
Binary files a/assets/images/desktop/ui/captionInactive.png and b/assets/images/desktop/ui/captionInactive.png differ
diff --git a/buildnumber.txt b/buildnumber.txt
index 50ae8807..c7105757 100644
--- a/buildnumber.txt
+++ b/buildnumber.txt
@@ -1 +1 @@
-714
\ No newline at end of file
+732
\ No newline at end of file
diff --git a/source/funkin/desktop/DesktopMain.hx b/source/funkin/desktop/DesktopMain.hx
index 1b1fbac0..32b5342b 100644
--- a/source/funkin/desktop/DesktopMain.hx
+++ b/source/funkin/desktop/DesktopMain.hx
@@ -13,6 +13,7 @@ import flixel.FlxCamera;
import flixel.math.FlxPoint;
import funkin.desktop.editors.HelloWorld;
import funkin.desktop.windows.*;
+import funkin.desktop.theme.Theme;
class DesktopMain extends MusicBeatState {
public var oldScaleMode:BaseScaleMode;
@@ -25,8 +26,12 @@ class DesktopMain extends MusicBeatState {
public var mouseInput:MouseInput = new MouseInput();
+ public static var theme:Theme = null;
+
public override function create() {
super.create();
+
+ theme = Theme.loadFromAssets(Paths.getPath('images/desktop/ui.xml', TEXT, null));
instance = this;
FlxG.mouse.useSystemCursor = FlxG.mouse.visible = true;
diff --git a/source/funkin/desktop/theme/Theme.hx b/source/funkin/desktop/theme/Theme.hx
new file mode 100644
index 00000000..db41c401
--- /dev/null
+++ b/source/funkin/desktop/theme/Theme.hx
@@ -0,0 +1,107 @@
+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);
+ }
+
+ public var captionActive:ThemeData = new ThemeData();
+ public var captionInactive:ThemeData = new ThemeData();
+ public var captionButtons: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();
+ trace(name);
+ 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.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.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) {
+ // TODO: logs system
+ trace(e.details());
+ }
+ }
+}
+
+class ThemeData implements IFlxDestroyable {
+ public var sprite:String = "";
+
+ public var textColor: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 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();
+ margin = null;
+ }
+ if (size != null) {
+ size.put();
+ size = null;
+ }
+ if (offset != null) {
+ offset.put();
+ offset = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/funkin/desktop/windows/Window.hx b/source/funkin/desktop/windows/Window.hx
index 4db01ca0..78860997 100644
--- a/source/funkin/desktop/windows/Window.hx
+++ b/source/funkin/desktop/windows/Window.hx
@@ -55,19 +55,26 @@ class Window extends FlxTypedGroup {
}
public function new(content:WindowContent) {
super();
- windowFrame = new FlxUI9SliceSprite(0, 0, Paths.image('desktop/windowFrame'), new Rectangle(10, 10), [3, 3, 6, 6]);
+ windowFrame = new FlxUI9SliceSprite(0, 0,
+ Paths.image(DesktopMain.theme.captionActive.sprite),
+ new Rectangle(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)
+ ]);
add(windowFrame);
caption = new FlxUIText(24, 4, 0, content.title);
captionButtons = new FlxTypedSpriteGroup();
for(i in 0...3) {
var btn = new WindowCaptionButton(this, i);
- btn.x = (i+1) * -18;
+ btn.x = (i+1) * -(DesktopMain.theme.captionButtons.size.x + DesktopMain.theme.captionButtons.margin.x);
captionButtons.add(btn);
}
add(caption);
- dragHitbox = new WindowDragHitbox(4, 4, 4, 18);
+ dragHitbox = new WindowDragHitbox(DesktopMain.theme.captionActive.left, DesktopMain.theme.captionActive.left, DesktopMain.theme.captionActive.left, DesktopMain.theme.captionActive.top);
dragHitbox.parent = this;
add(dragHitbox);
@@ -158,12 +165,17 @@ class Window extends FlxTypedGroup {
content.winY = windowCaptionCamera.y = y;
@:privateAccess content.__noParentUpdate = false;
for(e in windowCameras) {
- e.camera.x = x + 4;
- e.camera.y = y + 23;
+ 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;
+ }
var i = members.length;
var shouldCancel = DesktopMain.instance.mouseInput.overlapsRect(this, new Rectangle(0, 0, windowCaptionCamera.width, windowCaptionCamera.height), windowCaptionCamera);
@@ -184,14 +196,12 @@ class Window extends FlxTypedGroup {
public function close() {
__closing = true;
- DesktopMain.instance.windows.remove(this, true);
- destroy();
}
public function updateWindowFrame() {
- windowFrame.resize(windowWidth + 4 + 4, windowHeight + 23 + 4);
- windowCaptionCamera.setSize(windowWidth + 4 + 4, windowHeight + 23 + 4);
- captionButtons.setPosition(windowWidth + 4, 4);
+ windowFrame.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) {
diff --git a/source/funkin/desktop/windows/WindowCaptionButton.hx b/source/funkin/desktop/windows/WindowCaptionButton.hx
index af78f15f..1ac3627a 100644
--- a/source/funkin/desktop/windows/WindowCaptionButton.hx
+++ b/source/funkin/desktop/windows/WindowCaptionButton.hx
@@ -1,38 +1,59 @@
package funkin.desktop.windows;
-import flixel.addons.ui.FlxUIButton;
import flixel.FlxSprite;
-class WindowCaptionButton extends FlxUIButton {
+class WindowCaptionButton extends FlxSprite {
public var icon:FlxSprite;
+ public var window:Window;
public function new(window:Window, i:Int) {
- super(0, 0, "", function() {
- switch(i) {
- case 0:
- window.close();
- }
- });
+ // super(0, 0, "", function() {
+ // switch(i) {
+ // case 0:
+ // window.close();
+ // }
+ // });
+ super(0, 0);
+ this.window = window;
ID = i;
- resize(18, 18);
- color = (i > 0) ? 0xFF8888FF : 0xFFFF0000;
- icon = new FlxSprite(0, 0).loadGraphic(Paths.image('desktop/captionButtons'), true, 18, 18);
- icon.animation.add("button", [switch(i) {
- case 0: 2;
- case 1: 1;
- case 2: 0;
- default: i;
- }]);
- icon.animation.play("button");
+ loadGraphic(Paths.image(DesktopMain.theme.captionButtons.sprite), true, Std.int(DesktopMain.theme.captionButtons.size.x), Std.int(DesktopMain.theme.captionButtons.size.y));
+ animation.add("button", [for(l in 0...6) i+(l*3)], 0, true);
+ animation.play("button");
+
+ // resize(18, 18);
+ // color = (i > 0) ? 0xFF8888FF : 0xFFFF0000;
}
public override function draw() {
super.draw();
+ }
- icon.setPosition(x, y);
- icon.cameras = this.cameras;
- icon.draw();
- icon.scrollFactor.set(scrollFactor.x, scrollFactor.y);
+ public override function update(elapsed:Float) {
+ if (animation.curAnim == null) {
+ super.update(elapsed);
+ return;
+ }
+ var mouseInput = DesktopMain.instance.mouseInput;
+ if (DesktopMain.instance.mouseInput.overlaps(this, camera)) {
+ if (mouseInput.justReleased) {
+ switch(ID) {
+ case 0:
+ window.close();
+ }
+ 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;
+ if (!window.focused) animation.curAnim.curFrame += 3;
+
+ super.update(elapsed);
}
}
\ No newline at end of file