mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-20 12:47:37 +07:00
Added native file chooser, fixed macOS prefs errors
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,6 +9,7 @@
|
|||||||
/desktop/mindustry-maps/
|
/desktop/mindustry-maps/
|
||||||
/desktop/gifexport/
|
/desktop/gifexport/
|
||||||
/core/lib/
|
/core/lib/
|
||||||
|
/annotations/build/
|
||||||
/kryonet/build/
|
/kryonet/build/
|
||||||
/server/build/
|
/server/build/
|
||||||
/android/assets/mindustry-maps/
|
/android/assets/mindustry-maps/
|
||||||
|
Binary file not shown.
BIN
core/assets/sprites/icon@2x.icns
Normal file
BIN
core/assets/sprites/icon@2x.icns
Normal file
Binary file not shown.
@ -6,6 +6,7 @@ import io.anuke.mindustry.core.ThreadHandler.ThreadProvider;
|
|||||||
import io.anuke.ucore.core.Settings;
|
import io.anuke.ucore.core.Settings;
|
||||||
import io.anuke.ucore.entities.Entity;
|
import io.anuke.ucore.entities.Entity;
|
||||||
import io.anuke.ucore.entities.EntityGroup;
|
import io.anuke.ucore.entities.EntityGroup;
|
||||||
|
import io.anuke.ucore.function.Consumer;
|
||||||
import io.anuke.ucore.scene.ui.TextField;
|
import io.anuke.ucore.scene.ui.TextField;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -63,6 +64,8 @@ public abstract class Platform {
|
|||||||
}
|
}
|
||||||
/**Only used for iOS or android: open the share menu for a map or save.*/
|
/**Only used for iOS or android: open the share menu for a map or save.*/
|
||||||
public void shareFile(FileHandle file){}
|
public void shareFile(FileHandle file){}
|
||||||
|
/**Show a file chooser. Desktop only.*/
|
||||||
|
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String... filetypes){}
|
||||||
/**Use the default thread provider from the kryonet module for this.*/
|
/**Use the default thread provider from the kryonet module for this.*/
|
||||||
public ThreadProvider getThreadProvider(){
|
public ThreadProvider getThreadProvider(){
|
||||||
return new ThreadProvider() {
|
return new ThreadProvider() {
|
||||||
|
@ -6,7 +6,6 @@ import com.badlogic.gdx.graphics.Color;
|
|||||||
import com.badlogic.gdx.graphics.Pixmap;
|
import com.badlogic.gdx.graphics.Pixmap;
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.Platform;
|
||||||
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.ColorMapper;
|
import io.anuke.mindustry.world.ColorMapper;
|
||||||
import io.anuke.mindustry.world.ColorMapper.BlockPair;
|
import io.anuke.mindustry.world.ColorMapper.BlockPair;
|
||||||
@ -43,7 +42,6 @@ public class MapEditorDialog extends Dialog{
|
|||||||
private MapSaveDialog saveDialog;
|
private MapSaveDialog saveDialog;
|
||||||
private MapResizeDialog resizeDialog;
|
private MapResizeDialog resizeDialog;
|
||||||
private ScrollPane pane;
|
private ScrollPane pane;
|
||||||
private FileChooser openFile, saveFile;
|
|
||||||
private boolean saved = false;
|
private boolean saved = false;
|
||||||
|
|
||||||
private ButtonGroup<ImageButton> blockgroup;
|
private ButtonGroup<ImageButton> blockgroup;
|
||||||
@ -56,25 +54,6 @@ public class MapEditorDialog extends Dialog{
|
|||||||
dialog = new MapGenerateDialog(editor);
|
dialog = new MapGenerateDialog(editor);
|
||||||
view = new MapView(editor);
|
view = new MapView(editor);
|
||||||
|
|
||||||
openFile = new FileChooser("$text.loadimage", FileChooser.pngFilter, true, this::tryLoadMap);
|
|
||||||
|
|
||||||
saveFile = new FileChooser("$saveimage", false, file -> {
|
|
||||||
if(!file.extension().toLowerCase().equals(".png")){
|
|
||||||
file = file.parent().child(file.nameWithoutExtension() + ".png");
|
|
||||||
}
|
|
||||||
FileHandle result = file;
|
|
||||||
ui.loadfrag.show();
|
|
||||||
Timers.run(3f, () -> {
|
|
||||||
try{
|
|
||||||
Pixmaps.write(editor.pixmap(), result);
|
|
||||||
}catch (Exception e){
|
|
||||||
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
|
|
||||||
if(!mobile) Log.err(e);
|
|
||||||
}
|
|
||||||
ui.loadfrag.hide();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
loadDialog = new MapLoadDialog(map -> {
|
loadDialog = new MapLoadDialog(map -> {
|
||||||
saveDialog.setFieldText(map.name);
|
saveDialog.setFieldText(map.name);
|
||||||
ui.loadfrag.show();
|
ui.loadfrag.show();
|
||||||
@ -225,9 +204,9 @@ public class MapEditorDialog extends Dialog{
|
|||||||
//iOS does not support loading raw files.
|
//iOS does not support loading raw files.
|
||||||
if(!ios) {
|
if(!ios) {
|
||||||
|
|
||||||
new imagebutton("icon-load-image", isize, () ->
|
new imagebutton("icon-load-image", isize, () -> {
|
||||||
openFile.show()
|
Platform.instance.showFileChooser(Bundles.get("text.loadimage"), "Image Files", MapEditorDialog.this::tryLoadMap, true, "png");
|
||||||
).text("$text.editor.loadimage");
|
}).text("$text.editor.loadimage");
|
||||||
|
|
||||||
row();
|
row();
|
||||||
}
|
}
|
||||||
@ -235,7 +214,22 @@ public class MapEditorDialog extends Dialog{
|
|||||||
new imagebutton("icon-save-image", isize, () -> {
|
new imagebutton("icon-save-image", isize, () -> {
|
||||||
//iOS doesn't really support saving raw files. Sharing is used instead.
|
//iOS doesn't really support saving raw files. Sharing is used instead.
|
||||||
if(!ios){
|
if(!ios){
|
||||||
saveFile.show();
|
Platform.instance.showFileChooser(Bundles.get("text.saveimage"), "Image Files", file -> {
|
||||||
|
if(!file.extension().toLowerCase().equals(".png")){
|
||||||
|
file = file.parent().child(file.nameWithoutExtension() + ".png");
|
||||||
|
}
|
||||||
|
FileHandle result = file;
|
||||||
|
ui.loadfrag.show();
|
||||||
|
Timers.run(3f, () -> {
|
||||||
|
try{
|
||||||
|
Pixmaps.write(editor.pixmap(), result);
|
||||||
|
}catch (Exception e){
|
||||||
|
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
|
||||||
|
if(!mobile) Log.err(e);
|
||||||
|
}
|
||||||
|
ui.loadfrag.hide();
|
||||||
|
});
|
||||||
|
}, false, "png");
|
||||||
}else{
|
}else{
|
||||||
try{
|
try{
|
||||||
FileHandle file = Gdx.files.local(("map-" + ((editor.getMap().name == null) ? "unknown" : editor.getMap().name) + ".png"));
|
FileHandle file = Gdx.files.local(("map-" + ((editor.getMap().name == null) ? "unknown" : editor.getMap().name) + ".png"));
|
||||||
|
@ -8,6 +8,7 @@ import io.anuke.kryonet.KryoServer;
|
|||||||
import io.anuke.mindustry.Mindustry;
|
import io.anuke.mindustry.Mindustry;
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.Platform;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
|
import io.anuke.ucore.UCore;
|
||||||
import io.anuke.ucore.util.OS;
|
import io.anuke.ucore.util.OS;
|
||||||
|
|
||||||
public class DesktopLauncher {
|
public class DesktopLauncher {
|
||||||
@ -20,7 +21,7 @@ public class DesktopLauncher {
|
|||||||
config.setWindowedMode(960, 540);
|
config.setWindowedMode(960, 540);
|
||||||
config.setWindowIcon("sprites/icon.png");
|
config.setWindowIcon("sprites/icon.png");
|
||||||
if(OS.isMac) {
|
if(OS.isMac) {
|
||||||
config.setPreferencesConfig(System.getProperty("DocumentsDirectory"), FileType.Absolute);
|
config.setPreferencesConfig(UCore.getProperty("user.home") + "/Library/Application Support/", FileType.Absolute);
|
||||||
}
|
}
|
||||||
|
|
||||||
Platform.instance = new DesktopPlatform(arg);
|
Platform.instance = new DesktopPlatform(arg);
|
||||||
|
@ -3,17 +3,25 @@ package io.anuke.mindustry.desktop;
|
|||||||
import club.minnced.discord.rpc.DiscordEventHandlers;
|
import club.minnced.discord.rpc.DiscordEventHandlers;
|
||||||
import club.minnced.discord.rpc.DiscordRPC;
|
import club.minnced.discord.rpc.DiscordRPC;
|
||||||
import club.minnced.discord.rpc.DiscordRichPresence;
|
import club.minnced.discord.rpc.DiscordRichPresence;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.utils.Base64Coder;
|
import com.badlogic.gdx.utils.Base64Coder;
|
||||||
import io.anuke.kryonet.DefaultThreadImpl;
|
import io.anuke.kryonet.DefaultThreadImpl;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
import io.anuke.mindustry.core.ThreadHandler.ThreadProvider;
|
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.Platform;
|
||||||
|
import io.anuke.mindustry.core.ThreadHandler.ThreadProvider;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.ucore.UCore;
|
import io.anuke.ucore.UCore;
|
||||||
import io.anuke.ucore.core.Settings;
|
import io.anuke.ucore.core.Settings;
|
||||||
|
import io.anuke.ucore.function.Consumer;
|
||||||
import io.anuke.ucore.util.Strings;
|
import io.anuke.ucore.util.Strings;
|
||||||
|
import javafx.application.Application;
|
||||||
|
import javafx.stage.FileChooser;
|
||||||
|
import javafx.stage.FileChooser.ExtensionFilter;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import java.io.File;
|
||||||
import java.net.NetworkInterface;
|
import java.net.NetworkInterface;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
@ -40,6 +48,19 @@ public class DesktopPlatform extends Platform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String... filter) {
|
||||||
|
new Thread(() -> {
|
||||||
|
FxApp.text = text;
|
||||||
|
FxApp.cons = cons;
|
||||||
|
FxApp.filter = filter;
|
||||||
|
FxApp.open = open;
|
||||||
|
FxApp.open();
|
||||||
|
}){{
|
||||||
|
setDaemon(true);
|
||||||
|
}}.start();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String format(Date date){
|
public String format(Date date){
|
||||||
return format.format(date);
|
return format.format(date);
|
||||||
@ -139,4 +160,56 @@ public class DesktopPlatform extends Platform {
|
|||||||
System.arraycopy(bytes, 0, result, 0, bytes.length);
|
System.arraycopy(bytes, 0, result, 0, bytes.length);
|
||||||
return !new String(Base64Coder.encode(result)).equals("AAAAAAAAAOA=");
|
return !new String(Base64Coder.encode(result)).equals("AAAAAAAAAOA=");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class FxApp extends Application{
|
||||||
|
static String text;
|
||||||
|
static Consumer<FileHandle> cons;
|
||||||
|
static String[] filter;
|
||||||
|
static String content;
|
||||||
|
static boolean open;
|
||||||
|
|
||||||
|
private static FxApp instance;
|
||||||
|
|
||||||
|
static void open(){
|
||||||
|
if(instance == null){
|
||||||
|
launch();
|
||||||
|
}
|
||||||
|
ss();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ss(){
|
||||||
|
javafx.application.Platform.runLater(() -> instance.show());
|
||||||
|
}
|
||||||
|
|
||||||
|
public FxApp(){
|
||||||
|
instance = this;
|
||||||
|
ss();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(Stage stage){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show(){
|
||||||
|
for(int i = 0; i < filter.length; i ++){
|
||||||
|
filter[i] = "*." + filter[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
FileChooser chooser = new FileChooser();
|
||||||
|
chooser.setTitle(text);
|
||||||
|
chooser.getExtensionFilters().add(new ExtensionFilter(content, filter));
|
||||||
|
chooser.setInitialDirectory(new File(System.getProperty("user.home")));
|
||||||
|
|
||||||
|
File file;
|
||||||
|
if (open) {
|
||||||
|
file = chooser.showOpenDialog(null);
|
||||||
|
} else {
|
||||||
|
file = chooser.showSaveDialog(null);
|
||||||
|
}
|
||||||
|
if (file != null) {
|
||||||
|
cons.accept(Gdx.files.absolute(file.getAbsolutePath()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user