implement progress import-export

This commit is contained in:
RandomityGuy 2026-03-28 17:57:50 +00:00
parent a67cf3deaa
commit c4bbe512df
6 changed files with 164 additions and 48 deletions

BIN
data/ui/options/misc_d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
data/ui/options/misc_h.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
data/ui/options/misc_i.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
data/ui/options/misc_n.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

@ -246,59 +246,59 @@ class GuiScrollCtrl extends GuiControl {
}
public override function onMousePress(mouseState:MouseState) {
// if (Util.isTouchDevice()) {
this.pressed = true;
this.dirty = true;
this.updateScrollVisual();
this.prevMousePos = mouseState.position;
this.scrollVelocity = 0;
this.momentumActive = false;
this.lastMoveStamp = Timer.stamp();
// }
if (Util.isTouchDevice()) {
this.pressed = true;
this.dirty = true;
this.updateScrollVisual();
this.prevMousePos = mouseState.position;
this.scrollVelocity = 0;
this.momentumActive = false;
this.lastMoveStamp = Timer.stamp();
}
}
public override function onMouseRelease(mouseState:MouseState) {
// if (Util.isTouchDevice()) {
this.pressed = false;
this.dirty = true;
deltaY = 0;
this.updateScrollVisual();
this.momentumActive = Math.abs(scrollVelocity) > 0.01;
this.lastMoveStamp = 0;
// }
if (Util.isTouchDevice()) {
this.pressed = false;
this.dirty = true;
deltaY = 0;
this.updateScrollVisual();
this.momentumActive = Math.abs(scrollVelocity) > 0.01;
this.lastMoveStamp = 0;
}
}
public override function onMouseMove(mouseState:MouseState) {
// if (Util.isTouchDevice()) {
super.onMouseMove(mouseState);
if (this.pressed) {
var renderRect = this.getRenderRectangle();
var scrollExtentY = renderRect.extent.y;
var dy = (mouseState.position.y - this.prevMousePos.y) / ((maxScrollY * Settings.uiScale) / scrollExtentY);
deltaY = -dy;
this.scrollY -= dy;
this.prevMousePos = mouseState.position;
var now = Timer.stamp();
if (lastMoveStamp > 0) {
var dt = now - lastMoveStamp;
if (dt > 0)
scrollVelocity = -dy / dt;
if (Util.isTouchDevice()) {
super.onMouseMove(mouseState);
if (this.pressed) {
var renderRect = this.getRenderRectangle();
var scrollExtentY = renderRect.extent.y;
var dy = (mouseState.position.y - this.prevMousePos.y) / ((maxScrollY * Settings.uiScale) / scrollExtentY);
deltaY = -dy;
this.scrollY -= dy;
this.prevMousePos = mouseState.position;
var now = Timer.stamp();
if (lastMoveStamp > 0) {
var dt = now - lastMoveStamp;
if (dt > 0)
scrollVelocity = -dy / dt;
}
lastMoveStamp = now;
momentumActive = false;
this.updateScrollVisual();
}
lastMoveStamp = now;
momentumActive = false;
this.updateScrollVisual();
}
// }
}
public override function onMouseLeave(mouseState:MouseState) {
// if (Util.isTouchDevice()) {
this.pressed = false;
this.dirty = true;
this.updateScrollVisual();
this.momentumActive = Math.abs(scrollVelocity) > 0.01;
this.lastMoveStamp = 0;
// }
if (Util.isTouchDevice()) {
this.pressed = false;
this.dirty = true;
this.updateScrollVisual();
this.momentumActive = Math.abs(scrollVelocity) > 0.01;
this.lastMoveStamp = 0;
}
}
public override function update(dt:Float, mouseState:MouseState) {

View file

@ -1,5 +1,6 @@
package gui;
import haxe.DynamicAccess;
import hxd.BitmapData;
import h2d.filter.DropShadow;
import h2d.Text;
@ -70,10 +71,10 @@ class OptionsDlg extends GuiImage {
hotkeysBtn.extent = new Vector(134, 65);
window.addChild(hotkeysBtn);
var onlineBtn = new GuiImage(ResourceLoader.getResource("data/ui/options/online_i.png", ResourceLoader.getImage, this.imageResources).toTile());
onlineBtn.position = new Vector(548, 19);
onlineBtn.extent = new Vector(134, 65);
window.addChild(onlineBtn);
var miscBtn = new GuiButton(loadButtonImages('data/ui/options/misc'));
miscBtn.position = new Vector(548, 19);
miscBtn.extent = new Vector(134, 65);
window.addChild(miscBtn);
var generalPanel:GuiScrollCtrl = null;
@ -114,6 +115,10 @@ class OptionsDlg extends GuiImage {
hotkeysPanel.position = new Vector(30, 88);
hotkeysPanel.extent = new Vector(726, 394);
var miscPanel = new GuiControl();
miscPanel.position = new Vector(30, 88);
miscPanel.extent = new Vector(726, 394);
var markerFelt32fontdata = ResourceLoader.getFileEntry("data/font/MarkerFelt.fnt");
var markerFelt32b = new BitmapFont(markerFelt32fontdata.entry);
@:privateAccess markerFelt32b.loader = ResourceLoader.loader;
@ -470,6 +475,31 @@ class OptionsDlg extends GuiImage {
parent.addChild(remapBtn);
}
function makeButton(text:String, yPos:Int, buttonText:String, pressedAction:() -> Void, parent:GuiControl, right:Bool = false) {
var textObj = new GuiText(markerFelt32);
textObj.position = new Vector(right ? 368 : 5, yPos);
textObj.extent = new Vector(212, 14);
textObj.text.text = text;
textObj.text.textColor = 0xFFFFFF;
textObj.text.dropShadow = {
dx: 1 * Settings.uiScale,
dy: 1 * Settings.uiScale,
alpha: 0.5,
color: 0
};
parent.addChild(textObj);
var btn = new GuiButtonText(loadButtonImages("data/ui/options/bind"), markerFelt24);
btn.position = new Vector(right ? 363 + 203 : 203, yPos - 3);
btn.txtCtrl.text.text = buttonText;
btn.setExtent(new Vector(152, 49));
btn.pressedAction = (sender) -> {
pressedAction();
}
parent.addChild(btn);
}
if (Util.isTouchDevice()) {
var textObj = new GuiText(markerFelt32);
textObj.position = new Vector(5, 38);
@ -540,10 +570,85 @@ class OptionsDlg extends GuiImage {
hotkeysPanel, true);
}
// MISC PANEL
makeButton("Import Progress:", 38, "Import", () -> {
hxd.File.browse((sel) -> {
sel.load((data) -> {
try {
// convert to string
var jsonStr = data.toString();
// parse JSON
var json = haxe.Json.parse(jsonStr);
var highScoreData:DynamicAccess<Array<Score>> = json.highScores;
for (key => value in highScoreData) {
Settings.highScores.set(key, value);
}
var easterEggData:DynamicAccess<Float> = json.easterEggs;
if (easterEggData != null) {
for (key => value in easterEggData) {
Settings.easterEggs.set(key, value);
}
}
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Progress data imported successfully!"));
Settings.save();
} catch (e) {
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Failed to import progress data: " + e.message));
}
});
}, {
title: "Select a progress file to import",
fileTypes: [
{name: "JSON files", extensions: ["json"]},
{name: "All files", extensions: ["*"]}
],
});
}, miscPanel);
makeButton("Export Progress:", 38, "Export", () -> {
#if sys
#if MACOS_BUNDLE
// open the finder to that folder
Sys.command('open "${Settings.settingsDir}"');
#else
// Just open the folder in the explorer.exe
Sys.command('explorer.exe "${Settings.settingsDir}"');
#end
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("The settings.json file contains your progress data. You can copy it to another device or share it with others."));
#end
#if js
// Serialize Settings to JSON
var localStorage = js.Browser.getLocalStorage();
if (localStorage != null) {
var settingsData = localStorage.getItem("MBHaxeSettings");
if (settingsData != null) {
// Download this
var replayBytes = settingsData;
var blob = new js.html.Blob([haxe.io.Bytes.ofString(replayBytes).getData()], {
type: 'application/octet-stream'
});
var url = js.html.URL.createObjectURL(blob);
var fname = 'settings.json';
var element = js.Browser.document.createElement('a');
element.setAttribute('href', url);
element.setAttribute('download', fname);
element.style.display = 'none';
js.Browser.document.body.appendChild(element);
element.click();
js.Browser.document.body.removeChild(element);
js.html.URL.revokeObjectURL(url);
}
}
#end
}, miscPanel, true);
generalBtn.pressedAction = (e) -> {
if (currentTab != "general") {
currentTab = "general";
hotkeysPanel.parent.removeChild(hotkeysPanel);
hotkeysPanel.parent?.removeChild(hotkeysPanel);
miscPanel.parent?.removeChild(miscPanel);
generalPanel.scrollY = 0;
window.addChild(generalPanel);
MarbleGame.canvas.render(MarbleGame.canvas.scene2d); // Force refresh
@ -553,12 +658,23 @@ class OptionsDlg extends GuiImage {
hotkeysBtn.pressedAction = (e) -> {
if (currentTab != "hotkeys") {
currentTab = "hotkeys";
generalPanel.parent.removeChild(generalPanel);
generalPanel.parent?.removeChild(generalPanel);
miscPanel.parent?.removeChild(miscPanel);
window.addChild(hotkeysPanel);
MarbleGame.canvas.render(MarbleGame.canvas.scene2d); // Force refresh
}
};
miscBtn.pressedAction = (e) -> {
if (currentTab != "misc") {
currentTab = "misc";
generalPanel.parent?.removeChild(generalPanel);
hotkeysPanel.parent?.removeChild(hotkeysPanel);
window.addChild(miscPanel);
MarbleGame.canvas.render(MarbleGame.canvas.scene2d); // Force refresh
}
};
// // Touch Controls buttons???
// if (Util.isTouchDevice()) {
// var touchControlsTxt = new GuiText(domcasual24);