Explorar o código

tools: use resource name when loading or saving a level

Daniele Bartolini %!s(int64=5) %!d(string=hai) anos
pai
achega
6bbf916c5d

+ 1 - 0
tools/config.vala

@@ -30,5 +30,6 @@ const uint16 CROWN_DEFAULT_SERVER_PORT = 10618;
 
 
 const string LEVEL_EDITOR_BOOT_DIR = "core/editors/level_editor";
 const string LEVEL_EDITOR_BOOT_DIR = "core/editors/level_editor";
 const string UNIT_PREVIEW_BOOT_DIR = "core/editors/unit_preview";
 const string UNIT_PREVIEW_BOOT_DIR = "core/editors/unit_preview";
+const string LEVEL_NONE = "";
 
 
 }
 }

+ 20 - 11
tools/level_editor/level.vala

@@ -24,6 +24,7 @@ public class Level
 	public uint _num_units;
 	public uint _num_units;
 	public uint _num_sounds;
 	public uint _num_sounds;
 
 
+	public string _name;
 	public string _path;
 	public string _path;
 
 
 	// Signals
 	// Signals
@@ -61,32 +62,40 @@ public class Level
 		_num_units = 0;
 		_num_units = 0;
 		_num_sounds = 0;
 		_num_sounds = 0;
 
 
+		_name = null;
 		_path = null;
 		_path = null;
 	}
 	}
 
 
-	/// Loads the level from @a path.
-	public void load(string path)
+	public void load(string name)
 	{
 	{
 		reset();
 		reset();
-		_db.load(path);
 
 
+		string path = Path.build_filename(_project.source_dir(), name + ".level");
+
+		_db.load(path);
+		_name = name;
 		_path = path;
 		_path = path;
 	}
 	}
 
 
-	/// Saves the level to @a path.
-	public void save(string path)
+	public void load_empty_level()
 	{
 	{
-		_db.save(path);
+		reset();
 
 
-		_path = path;
+		string name = "core/editors/levels/empty";
+		string path = Path.build_filename(_project.toolchain_dir(), name + ".level");
+
+		_db.load(path);
+		_name = name;
+		_path = null;
 	}
 	}
 
 
-	/// Loads the empty level template.
-	public void load_empty_level()
+	public void save(string name)
 	{
 	{
-		load(Path.build_filename(_project.toolchain_dir(), "core/editors/levels/empty.level"));
+		string path = Path.build_filename(_project.source_dir(), name + ".level");
 
 
-		_path = null;
+		_db.save(path);
+		_path = path;
+		_name = name;
 	}
 	}
 
 
 	public void spawn_unit(Guid id, string name, Vector3 pos, Quaternion rot, Vector3 scl)
 	public void spawn_unit(Guid id, string name, Vector3 pos, Quaternion rot, Vector3 scl)

+ 97 - 49
tools/level_editor/level_editor.vala

@@ -205,7 +205,7 @@ public class LevelEditorApplication : Gtk.Application
 	// Command line options
 	// Command line options
 	private string? _source_dir = null;
 	private string? _source_dir = null;
 	private string _toolchain_dir = "";
 	private string _toolchain_dir = "";
-	private string? _level_resource = null;
+	private string _level_resource = "";
 	private User _user;
 	private User _user;
 
 
 	// Editor state
 	// Editor state
@@ -806,7 +806,7 @@ public class LevelEditorApplication : Gtk.Application
 		Gtk.Label label = new Gtk.Label(null);
 		Gtk.Label label = new Gtk.Label(null);
 		label.set_markup("Data Compiler disconnected.\rTry to <a href=\"restart\">restart</a> compiler to continue.");
 		label.set_markup("Data Compiler disconnected.\rTry to <a href=\"restart\">restart</a> compiler to continue.");
 		label.activate_link.connect(() => {
 		label.activate_link.connect(() => {
-			restart_backend(_project.source_dir(), _level._path);
+			restart_backend(_project.source_dir(), _level._name);
 			return true;
 			return true;
 		});
 		});
 
 
@@ -818,20 +818,22 @@ public class LevelEditorApplication : Gtk.Application
 		Gtk.Label label = new Gtk.Label(null);
 		Gtk.Label label = new Gtk.Label(null);
 		label.set_markup("Data compilation failed.\rFix errors and <a href=\"restart\">restart</a> compiler to continue.");
 		label.set_markup("Data compilation failed.\rFix errors and <a href=\"restart\">restart</a> compiler to continue.");
 		label.activate_link.connect(() => {
 		label.activate_link.connect(() => {
-			restart_backend(_project.source_dir(), _level._path);
+			restart_backend(_project.source_dir(), _level._name);
 			return true;
 			return true;
 		});
 		});
 
 
 		return label;
 		return label;
 	}
 	}
 
 
-	public void restart_backend(string source_dir, string? level_resource)
+	public void restart_backend(string source_dir, string level_name)
 	{
 	{
 		stop_backend();
 		stop_backend();
 
 
-		_project.load(source_dir);
-		if (level_resource != null)
-			_level.load(Path.build_filename(_project.source_dir(), level_resource + ".level"));
+		string sd = source_dir;
+		string ln = level_name;
+		_project.load(sd);
+		if (ln != "")
+			_level.load(ln);
 		else
 		else
 			_level.load_empty_level();
 			_level.load_empty_level();
 
 
@@ -890,12 +892,13 @@ public class LevelEditorApplication : Gtk.Application
 
 
 	private void stop_backend()
 	private void stop_backend()
 	{
 	{
-		_level.reset();
-		_project.reset();
-
 		stop_game();
 		stop_game();
 		stop_editor();
 		stop_editor();
+		stop_data_compiler();
+	}
 
 
+	private void stop_data_compiler()
+	{
 		if (_compiler != null)
 		if (_compiler != null)
 		{
 		{
 			// Explicit call to this function should not produce error messages.
 			// Explicit call to this function should not produce error messages.
@@ -1201,44 +1204,14 @@ public class LevelEditorApplication : Gtk.Application
 		_level.send_level();
 		_level.send_level();
 	}
 	}
 
 
-	private void load_level(string level)
+	private void load_level(string name)
 	{
 	{
-		string filename = level;
-
-		if (filename == "")
-		{
-			Gtk.FileChooserDialog fcd = new Gtk.FileChooserDialog("Open Level..."
-				, this.active_window
-				, FileChooserAction.OPEN
-				, "Cancel"
-				, ResponseType.CANCEL
-				, "Open"
-				, ResponseType.ACCEPT
-				);
-			fcd.add_filter(_file_filter);
-			fcd.set_current_folder(_project.source_dir());
-
-			if (fcd.run() == ResponseType.ACCEPT)
-				filename = fcd.get_filename();
-
-			fcd.destroy();
-		}
-
-		if (filename == "")
+		if (name == _level._name)
 			return;
 			return;
 
 
-		if (!_project.path_is_within_dir(filename, _project.source_dir()))
-		{
-			loge("File must be within `%s`".printf(_project.source_dir()));
-			return;
-		}
-
-		if (filename.has_suffix(".level") && filename != _level._path)
-		{
-			_level.load(filename);
-			_level.send_level();
-			send_state();
-		}
+		_level.load(name);
+		_level.send_level();
+		send_state();
 	}
 	}
 
 
 	private bool save_as(string? filename)
 	private bool save_as(string? filename)
@@ -1312,7 +1285,12 @@ public class LevelEditorApplication : Gtk.Application
 			fcd.destroy();
 			fcd.destroy();
 		}
 		}
 
 
-		_level.save(path);
+		// Save level
+		string resource_filename = _project.absolute_path_to_resource_filename(path);
+		string resource_path     = _project.resource_filename_to_resource_path(resource_filename);
+		string resource_name     = _project.resource_path_to_resource_name(resource_path);
+
+		_level.save(resource_name);
 		_statusbar.set_temporary_message("Saved %s".printf(_level._path));
 		_statusbar.set_temporary_message("Saved %s".printf(_level._path));
 		return true;
 		return true;
 	}
 	}
@@ -1381,18 +1359,88 @@ public class LevelEditorApplication : Gtk.Application
 		}
 		}
 	}
 	}
 
 
+	private void on_open_level_from_menubar(GLib.SimpleAction action, GLib.Variant? param)
+	{
+		string path = "";
+
+		Gtk.FileChooserDialog fcd = new Gtk.FileChooserDialog("Open Level..."
+			, this.active_window
+			, FileChooserAction.OPEN
+			, "Cancel"
+			, ResponseType.CANCEL
+			, "Open"
+			, ResponseType.ACCEPT
+			);
+		fcd.add_filter(_file_filter);
+		fcd.set_current_folder(_project.source_dir());
+
+		int err = 1;
+		int rt = ResponseType.CANCEL;
+		do
+		{
+			// Select the file
+			rt = fcd.run();
+			if (rt != ResponseType.ACCEPT)
+			{
+				fcd.destroy();
+				return;
+			}
+			path = fcd.get_filename();
+			err = 0;
+
+			// Append file extension
+			if (!path.has_suffix(".level"))
+				path += ".level";
+
+			if (!_project.path_is_within_dir(path, _project.source_dir()))
+			{
+				Gtk.MessageDialog md = new Gtk.MessageDialog(fcd
+					, DialogFlags.MODAL
+					, MessageType.WARNING
+					, Gtk.ButtonsType.OK
+					, "The file must be within the source directory."
+					);
+				md.set_default_response(ResponseType.OK);
+
+				md.run();
+				md.destroy();
+				fcd.set_current_folder(_project.source_dir());
+				err = 1;
+				continue;
+			}
+		}
+		while (err != 0);
+
+		fcd.destroy();
+
+		assert(path != "");
+
+		// Load level
+		string resource_filename = _project.absolute_path_to_resource_filename(path);
+		string resource_path     = _project.resource_filename_to_resource_path(resource_filename);
+		string resource_name     = _project.resource_path_to_resource_name(resource_path);
+
+		load_level(resource_name);
+	}
+
 	private void on_open_level(GLib.SimpleAction action, GLib.Variant? param)
 	private void on_open_level(GLib.SimpleAction action, GLib.Variant? param)
 	{
 	{
 		int rt = ResponseType.YES;
 		int rt = ResponseType.YES;
 
 
-		if (_level._path == param.get_string())
+		string level_name = param.get_string();
+		if (level_name != "" && level_name == _level._name)
 			return;
 			return;
 
 
 		if (_database.changed())
 		if (_database.changed())
 			rt = run_level_changed_dialog(this.active_window);
 			rt = run_level_changed_dialog(this.active_window);
 
 
 		if (!_database.changed() || rt == ResponseType.YES && save() || rt == ResponseType.NO)
 		if (!_database.changed() || rt == ResponseType.YES && save() || rt == ResponseType.NO)
-			load_level(param.get_string());
+		{
+			if (level_name != "")
+				load_level(level_name);
+			else // Action invoked from menubar File > Open Level...
+				on_open_level_from_menubar(action, param);
+		}
 	}
 	}
 
 
 	private void on_open_project(GLib.SimpleAction action, GLib.Variant? param)
 	private void on_open_project(GLib.SimpleAction action, GLib.Variant? param)
@@ -1413,7 +1461,7 @@ public class LevelEditorApplication : Gtk.Application
 				return;
 				return;
 
 
 			logi("Loading project: `%s`...".printf(source_dir));
 			logi("Loading project: `%s`...".printf(source_dir));
-			restart_backend(source_dir, null);
+			restart_backend(source_dir, LEVEL_NONE);
 		}
 		}
 	}
 	}
 
 

+ 1 - 1
tools/level_editor/panel_new_project.vala

@@ -77,7 +77,7 @@ public class PanelNewProject : Gtk.Viewport
 			_user.add_recent_project(source_dir, _entry_name.text);
 			_user.add_recent_project(source_dir, _entry_name.text);
 			_application.show_panel("main_vbox");
 			_application.show_panel("main_vbox");
 			_project.create_initial_files(source_dir);
 			_project.create_initial_files(source_dir);
-			_application.restart_backend(source_dir, null);
+			_application.restart_backend(source_dir, LEVEL_NONE);
 		});
 		});
 	}
 	}
 }
 }

+ 1 - 1
tools/level_editor/panel_projects_list.vala

@@ -122,7 +122,7 @@ public class PanelProjectsList : Gtk.ScrolledWindow
 			_list_projects.invalidate_sort();
 			_list_projects.invalidate_sort();
 			_user.touch_recent_project(row.get_data("source_dir"), mtime);
 			_user.touch_recent_project(row.get_data("source_dir"), mtime);
 			_application.show_panel("main_vbox", Gtk.StackTransitionType.NONE);
 			_application.show_panel("main_vbox", Gtk.StackTransitionType.NONE);
-			_application.restart_backend(source_dir, null);
+			_application.restart_backend(source_dir, LEVEL_NONE);
 		});
 		});
 		hbox.pack_end(button_open, false, false, 0);
 		hbox.pack_end(button_open, false, false, 0);
 
 

+ 13 - 0
tools/level_editor/project.vala

@@ -52,6 +52,8 @@ public class Project
 
 
 	public void load(string source_dir)
 	public void load(string source_dir)
 	{
 	{
+		reset();
+
 		_source_dir = File.new_for_path(source_dir);
 		_source_dir = File.new_for_path(source_dir);
 		_data_dir   = File.new_for_path(_source_dir.get_path() + "_" + _platform);
 		_data_dir   = File.new_for_path(_source_dir.get_path() + "_" + _platform);
 
 
@@ -421,6 +423,17 @@ public class Project
 		return path.replace("\\", "/");
 		return path.replace("\\", "/");
 	}
 	}
 
 
+	public string resource_filename_to_resource_path(string filename)
+	{
+		return filename.substring(0, filename.last_index_of_char('.'));
+	}
+
+	public string absolute_path_to_resource_filename(string path)
+	{
+		assert(path.has_prefix(_source_dir.get_path()));
+		return _source_dir.get_relative_path(File.new_for_path(path));
+	}
+
 	public int import_sprites(SList<string> filenames, string destination_dir)
 	public int import_sprites(SList<string> filenames, string destination_dir)
 	{
 	{
 		Hashtable importer_settings = null;
 		Hashtable importer_settings = null;

+ 2 - 3
tools/level_editor/project_browser.vala

@@ -467,17 +467,16 @@ public class ProjectBrowser : Gtk.Box
 					Value name;
 					Value name;
 					_tree_view.model.get_value(iter, ProjectStore.Column.NAME, out name);
 					_tree_view.model.get_value(iter, ProjectStore.Column.NAME, out name);
 
 
-					GLib.File file = GLib.File.new_for_path(ProjectBrowser.filename(_project, (string)type, (string)name));
-
 					if (type == "level")
 					if (type == "level")
 					{
 					{
 						Gtk.Application app = ((Gtk.Window)this.get_toplevel()).application;
 						Gtk.Application app = ((Gtk.Window)this.get_toplevel()).application;
-						app.activate_action("open-level", file.get_path());
+						app.activate_action("open-level", (string)name);
 					}
 					}
 					else
 					else
 					{
 					{
 						try
 						try
 						{
 						{
+							GLib.File file = GLib.File.new_for_path(ProjectBrowser.filename(_project, (string)type, (string)name));
 							GLib.AppInfo? app = file.query_default_handler();
 							GLib.AppInfo? app = file.query_default_handler();
 							GLib.List<GLib.File> files = new GLib.List<GLib.File>();
 							GLib.List<GLib.File> files = new GLib.List<GLib.File>();
 							files.append(file);
 							files.append(file);