Procházet zdrojové kódy

tools: move EditorView creation logic outside ResourceChooser

Daniele Bartolini před 3 roky
rodič
revize
44b982047e

+ 166 - 3
tools/level_editor/level_editor.vala

@@ -271,11 +271,14 @@ public class LevelEditorApplication : Gtk.Application
 	private GLib.Subprocess _compiler_process;
 	private GLib.Subprocess _editor_process;
 	private GLib.Subprocess _game_process;
+	private GLib.Subprocess _resource_preview_process;
 	private GLib.SourceFunc _stop_data_compiler_callback = null;
 	private GLib.SourceFunc _stop_editor_callback = null;
 	private GLib.SourceFunc _stop_game_callback = null;
+	private GLib.SourceFunc _stop_resource_preview_callback = null;
 	private ConsoleClient _compiler;
 	public ConsoleClient _editor;
+	private ConsoleClient _resource_preview;
 	private ConsoleClient _game;
 
 	// Level data
@@ -289,6 +292,7 @@ public class LevelEditorApplication : Gtk.Application
 	private Gtk.CssProvider _css_provider;
 	private ProjectBrowser _project_browser;
 	private EditorView _editor_view;
+	private EditorView _resource_preview_view;
 	private LevelTreeView _level_treeview;
 	private LevelLayersTreeView _level_layers_treeview;
 	private PropertiesView _properties_view;
@@ -311,6 +315,11 @@ public class LevelEditorApplication : Gtk.Application
 	private Gtk.Label _editor_stack_disconnected_label;
 	private Gtk.Label _editor_stack_oops_label;
 
+	public Gtk.Stack _resource_preview_stack;
+	public Gtk.Label _resource_preview_disconnected_label;
+	public Gtk.Label _resource_preview_oops_label;
+	public Gtk.Label _resource_preview_no_preview_label;
+
 	private Gtk.Stack _inspector_stack;
 	private Gtk.Label _inspector_stack_compiling_data_label;
 	private Gtk.Label _inspector_stack_connecting_to_data_compiler_label;
@@ -438,6 +447,10 @@ public class LevelEditorApplication : Gtk.Application
 		_editor.connected.connect(on_editor_connected);
 		_editor.message_received.connect(on_message_received);
 
+		_resource_preview = new ConsoleClient();
+		_resource_preview.connected.connect(on_resource_preview_connected);
+		_resource_preview.message_received.connect(on_resource_preview_message_received);
+
 		_game = new ConsoleClient();
 		_game.connected.connect(on_game_connected);
 		_game.message_received.connect(on_message_received);
@@ -512,6 +525,22 @@ public class LevelEditorApplication : Gtk.Application
 			});
 		_editor_stack.add(_editor_stack_oops_label);
 
+		_resource_preview_stack = new Gtk.Stack();
+		_resource_preview_no_preview_label = new Gtk.Label("No Preview");
+		_resource_preview_no_preview_label.set_size_request(300, 300);
+		_resource_preview_stack.add(_resource_preview_no_preview_label);
+		_resource_preview_disconnected_label = new Gtk.Label("Disconnected");
+		_resource_preview_stack.add(_resource_preview_disconnected_label);
+		_resource_preview_oops_label = new Gtk.Label(null);
+		_resource_preview_oops_label.set_markup("Something went wrong.\rTry to <a href=\"restart\">restart</a> this view.");
+		_resource_preview_oops_label.activate_link.connect(() => {
+				restart_resource_preview.begin((obj, res) => {
+						restart_resource_preview.end(res);
+					});
+				return true;
+			});
+		_resource_preview_stack.add(_resource_preview_oops_label);
+
 		_inspector_stack = new Gtk.Stack();
 		_inspector_stack_compiling_data_label = compiling_data_label();
 		_inspector_stack.add(_inspector_stack_compiling_data_label);
@@ -575,8 +604,14 @@ public class LevelEditorApplication : Gtk.Application
 			});
 		_resource_popover.modal = true;
 
-		_resource_chooser = new ResourceChooser(_project, _project_store, true);
+		_resource_chooser = new ResourceChooser(_project, _project_store, _resource_preview_stack, _resource_preview);
 		_resource_chooser.resource_selected.connect(on_resource_browser_resource_selected);
+		_resource_chooser.destroy.connect(() => {
+				stop_resource_preview.begin((obj, res) => {
+						stop_resource_preview.end(res);
+					});
+			});
+
 		_resource_popover.add(_resource_chooser);
 
 		_level_tree_view_notebook = new Notebook();
@@ -799,6 +834,38 @@ public class LevelEditorApplication : Gtk.Application
 		_editor_stack.set_visible_child(_editor_stack_oops_label);
 	}
 
+	private void on_resource_preview_connected(string address, int port)
+	{
+		logi("Connected to preview@%s:%d".printf(address, port));
+
+		// Start receiving data from the editor view.
+		_resource_preview.receive_async();
+	}
+
+	private void on_resource_preview_disconnected()
+	{
+		logi("Disconnected from preview");
+
+		if (_stop_resource_preview_callback != null)
+			_stop_resource_preview_callback();
+	}
+
+	private void on_resource_preview_disconnected_unexpected()
+	{
+		logw("Disconnected from preview unexpectedly");
+		int exit_status;
+		wait_process(out exit_status, _resource_preview_process);
+		_resource_preview_process = null;
+
+		_resource_preview_stack.set_visible_child(_resource_preview_oops_label);
+	}
+
+	private void on_resource_preview_message_received(ConsoleClient client, uint8[] json)
+	{
+		// Ignore the message content.
+		client.receive_async();
+	}
+
 	private void on_game_connected(string address, int port)
 	{
 		logi("Connected to game@%s:%d".printf(address, port));
@@ -1175,9 +1242,58 @@ public class LevelEditorApplication : Gtk.Application
 		}
 	}
 
+	private async void start_resource_preview(uint window_xid)
+	{
+		if (window_xid == 0)
+			return;
+
+		// Spawn unit_preview.
+		string args[] =
+		{
+			ENGINE_EXE,
+			"--data-dir",
+			_project.data_dir(),
+			"--boot-dir",
+			UNIT_PREVIEW_BOOT_DIR,
+			"--parent-window",
+			window_xid.to_string(),
+			"--console-port",
+			UNIT_PREVIEW_TCP_PORT.to_string(),
+			"--wait-console",
+			"--pumped",
+			null
+		};
+		GLib.SubprocessLauncher sl = new GLib.SubprocessLauncher(SubprocessFlags.NONE);
+		sl.set_cwd(ENGINE_DIR);
+		try {
+			_editor_process = sl.spawnv(args);
+		}
+		catch (Error e) {
+			loge(e.message);
+		}
+
+		// It is an error if the unit_preview disconnects after here.
+		_resource_preview.disconnected.disconnect(on_resource_preview_disconnected);
+		_resource_preview.disconnected.connect(on_resource_preview_disconnected_unexpected);
+
+		// Try to connect to unit_preview.
+		int tries = yield _resource_preview.connect_async(UNIT_PREVIEW_ADDRESS
+			, UNIT_PREVIEW_TCP_PORT
+			, EDITOR_CONNECTION_TRIES
+			, EDITOR_CONNECTION_INTERVAL
+			);
+		if (tries == EDITOR_CONNECTION_TRIES) {
+			loge("Cannot connect to unit_preview.");
+			return;
+		}
+
+		// FIXME: This should be done in ResourceChooser.
+		_resource_chooser._tree_view.set_cursor(new Gtk.TreePath.first(), null, false);
+	}
+
 	private async void stop_editor()
 	{
-		yield _resource_chooser.stop_editor();
+		yield stop_resource_preview();
 
 		if (_editor != null) {
 			// Reset "disconnected" signal.
@@ -1201,6 +1317,30 @@ public class LevelEditorApplication : Gtk.Application
 		_editor_process = null;
 	}
 
+	public async void stop_resource_preview()
+	{
+		if (_resource_preview != null) {
+			// Reset "disconnected" signal.
+			_resource_preview.disconnected.disconnect(on_resource_preview_disconnected);
+			_resource_preview.disconnected.disconnect(on_resource_preview_disconnected_unexpected);
+
+			// Explicit call to this function should not produce error messages.
+			_resource_preview.disconnected.connect(on_resource_preview_disconnected);
+
+			if (_resource_preview.is_connected()) {
+				_stop_resource_preview_callback = stop_resource_preview.callback;
+				_resource_preview.send_script("Device.quit()");
+				yield; // Wait for ConsoleClient to disconnect.
+				_stop_resource_preview_callback = null;
+				_resource_preview_stack.set_visible_child(_resource_preview_disconnected_label);
+			}
+		}
+
+		int exit_status;
+		wait_process(out exit_status, _resource_preview_process);
+		_resource_preview_process = null;
+	}
+
 	private async void restart_editor()
 	{
 		yield stop_editor();
@@ -1222,7 +1362,25 @@ public class LevelEditorApplication : Gtk.Application
 		_editor_stack.add(_editor_view_overlay);
 		_editor_stack.set_visible_child(_editor_view_overlay);
 
-		yield _resource_chooser.restart_editor();
+		yield restart_resource_preview();
+	}
+
+	private async void restart_resource_preview()
+	{
+		yield stop_resource_preview();
+
+		if (_resource_preview_view != null) {
+			_resource_preview_stack.remove(_resource_preview_view);
+			_resource_preview_view = null;
+		}
+
+		_resource_preview_view = new EditorView(_resource_preview, false);
+		_resource_preview_view.set_size_request(300, 300);
+		_resource_preview_view.realized.connect(on_resource_preview_view_realized);
+		_resource_preview_view.show_all();
+
+		_resource_preview_stack.add(_resource_preview_view);
+		_resource_preview_stack.set_visible_child(_resource_preview_view);
 	}
 
 	private async void start_game(StartGame sg)
@@ -1364,6 +1522,11 @@ public class LevelEditorApplication : Gtk.Application
 		start_editor.begin(_editor_view.window_id);
 	}
 
+	private async void on_resource_preview_view_realized()
+	{
+		start_resource_preview.begin(_resource_preview_view.window_id);
+	}
+
 	private void on_tool_changed(GLib.SimpleAction action, GLib.Variant? param)
 	{
 		string name = param.get_string();

+ 14 - 181
tools/level_editor/resource_chooser.vala

@@ -20,11 +20,9 @@ public class ResourceChooser : Gtk.Box
 {
 	// Data
 	public Project _project;
-	public GLib.Subprocess _editor_process;
-	public ConsoleClient _editor;
-	private GLib.SourceFunc _stop_editor_callback = null;
 	public Gtk.ListStore _list_store;
-	public bool _preview;
+	public Gtk.Stack? _editor_stack;
+	public ConsoleClient? _resource_preview;
 	public unowned UserFilter _user_filter;
 	public string _name;
 
@@ -35,28 +33,24 @@ public class ResourceChooser : Gtk.Box
 	public Gtk.TreeView _tree_view;
 	public Gtk.TreeSelection _tree_selection;
 	public Gtk.ScrolledWindow _scrolled_window;
-	public Gtk.Label _no_preview_label;
-	public Gtk.Label _disconnected_label;
-	public Gtk.Label _oops_label;
-	public Gtk.Stack _editor_stack;
-	public EditorView _editor_view;
 
 	// Signals
 	public signal void resource_selected(string type, string name);
 
-	public ResourceChooser(Project? project, ProjectStore project_store, bool preview)
+	public ResourceChooser(Project? project
+		, ProjectStore project_store
+		, Gtk.Stack? editor_stack = null
+		, ConsoleClient? resource_preview = null
+		)
 	{
 		Object(orientation: Gtk.Orientation.VERTICAL, spacing: 0);
 
 		// Data
 		_project = project;
 
-		_editor = new ConsoleClient();
-		_editor.connected.connect(on_editor_connected);
-		_editor.message_received.connect(on_editor_message_received);
-
 		_list_store = project_store._list_store;
-		_preview = preview;
+		_editor_stack = editor_stack;
+		_resource_preview = resource_preview;
 		_user_filter = user_filter;
 
 		// Widgets
@@ -123,33 +117,12 @@ public class ResourceChooser : Gtk.Box
 		_scrolled_window.add(_tree_view);
 		_scrolled_window.set_size_request(300, 400);
 
-		_editor_stack = new Gtk.Stack();
-
 		this.pack_start(_filter_entry, false, true, 0);
-		this.pack_start(_editor_stack, true, true, 0);
+		if (_editor_stack != null)
+			this.pack_start(_editor_stack, true, true, 0);
 		this.pack_start(_scrolled_window, true, true, 0);
 
-		_no_preview_label = new Gtk.Label("No Preview");
-		_no_preview_label.set_size_request(300, 300);
-		_editor_stack.add(_no_preview_label);
-		_disconnected_label = new Gtk.Label("Disconnected");
-		_editor_stack.add(_disconnected_label);
-		_oops_label = new Gtk.Label(null);
-		_oops_label.set_markup("Something went wrong.\rTry to <a href=\"restart\">restart</a> this view.");
-		_oops_label.activate_link.connect(() => {
-				restart_editor.begin((obj, res) => {
-						restart_editor.end(res);
-					});
-				return true;
-			});
-		_editor_stack.add(_oops_label);
-
-		this.destroy.connect(on_destroy);
 		this.unmap.connect(on_unmap);
-
-		restart_editor.begin((obj, res) => {
-				restart_editor.end(res);
-			});
 	}
 
 	private void on_row_activated(Gtk.TreePath path, TreeViewColumn column)
@@ -191,151 +164,11 @@ public class ResourceChooser : Gtk.Box
 		return Gdk.EVENT_PROPAGATE;
 	}
 
-	private void on_destroy()
-	{
-		stop_editor.begin((obj, res) => {
-				stop_editor.end(res);
-			});
-	}
-
 	private void on_unmap()
 	{
 		_filter_entry.text = "";
 	}
 
-	private async void start_editor(uint window_xid)
-	{
-		if (window_xid == 0)
-			return;
-
-		// Spawn unit_preview.
-		string args[] =
-		{
-			ENGINE_EXE
-			, "--data-dir"
-			, _project.data_dir()
-			, "--boot-dir"
-			, UNIT_PREVIEW_BOOT_DIR
-			, "--parent-window"
-			, window_xid.to_string()
-			, "--console-port"
-			, UNIT_PREVIEW_TCP_PORT.to_string()
-			, "--wait-console"
-			, "--pumped"
-			, null
-		};
-		GLib.SubprocessLauncher sl = new GLib.SubprocessLauncher(SubprocessFlags.NONE);
-		sl.set_cwd(ENGINE_DIR);
-		try {
-			_editor_process = sl.spawnv(args);
-		}
-		catch (Error e) {
-			loge(e.message);
-		}
-
-		// It is an error if the unit_preview disconnects after here.
-		_editor.disconnected.disconnect(on_editor_disconnected);
-		_editor.disconnected.connect(on_editor_disconnected_unexpected);
-
-		// Try to connect to unit_preview.
-		int tries = yield _editor.connect_async(UNIT_PREVIEW_ADDRESS
-			, UNIT_PREVIEW_TCP_PORT
-			, EDITOR_CONNECTION_TRIES
-			, EDITOR_CONNECTION_INTERVAL
-			);
-		if (tries == EDITOR_CONNECTION_TRIES) {
-			loge("Cannot connect to unit_preview.");
-			return;
-		}
-
-		_tree_view.set_cursor(new Gtk.TreePath.first(), null, false);
-	}
-
-	public async void stop_editor()
-	{
-		if (!_preview)
-			return;
-
-		if (_editor != null) {
-			// Reset "disconnected" signal.
-			_editor.disconnected.disconnect(on_editor_disconnected);
-			_editor.disconnected.disconnect(on_editor_disconnected_unexpected);
-
-			// Explicit call to this function should not produce error messages.
-			_editor.disconnected.connect(on_editor_disconnected);
-
-			if (_editor.is_connected()) {
-				_stop_editor_callback = stop_editor.callback;
-				_editor.send_script("Device.quit()");
-				yield; // Wait for ConsoleClient to disconnect.
-				_stop_editor_callback = null;
-				_editor_stack.set_visible_child(_disconnected_label);
-			}
-		}
-
-		int exit_status;
-		wait_process(out exit_status, _editor_process);
-		_editor_process = null;
-	}
-
-	public async void restart_editor()
-	{
-		if (!_preview)
-			return;
-
-		yield stop_editor();
-
-		if (_editor_view != null) {
-			_editor_stack.remove(_editor_view);
-			_editor_view = null;
-		}
-
-		_editor_view = new EditorView(_editor, false);
-		_editor_view.set_size_request(300, 300);
-		_editor_view.realized.connect(on_editor_view_realized);
-		_editor_view.show_all();
-
-		_editor_stack.add(_editor_view);
-		_editor_stack.set_visible_child(_editor_view);
-	}
-
-	private void on_editor_connected(string address, int port)
-	{
-		logi("Connected to preview@%s:%d".printf(address, port));
-
-		// Start receiving data from the editor view.
-		_editor.receive_async();
-	}
-
-	private void on_editor_disconnected()
-	{
-		logi("Disconnected from preview");
-
-		if (_stop_editor_callback != null)
-			_stop_editor_callback();
-	}
-
-	private void on_editor_disconnected_unexpected()
-	{
-		logw("Disconnected from preview unexpectedly");
-		int exit_status;
-		wait_process(out exit_status, _editor_process);
-		_editor_process = null;
-
-		_editor_stack.set_visible_child(_oops_label);
-	}
-
-	private void on_editor_message_received(ConsoleClient client, uint8[] json)
-	{
-		// Ignore the message content.
-		client.receive_async();
-	}
-
-	private void on_editor_view_realized()
-	{
-		start_editor.begin(_editor_view.window_id);
-	}
-
 	private void on_filter_entry_text_changed()
 	{
 		_tree_selection.changed.disconnect(on_tree_selection_changed);
@@ -382,7 +215,7 @@ public class ResourceChooser : Gtk.Box
 
 	private void on_tree_selection_changed()
 	{
-		if (_preview) {
+		if (_editor_stack != null) {
 			Gtk.TreeModel model;
 			Gtk.TreeIter iter;
 			if (_tree_selection.get_selected(out model, out iter)) {
@@ -390,8 +223,8 @@ public class ResourceChooser : Gtk.Box
 				Value type;
 				model.get_value(iter, ProjectStore.Column.NAME, out name);
 				model.get_value(iter, ProjectStore.Column.TYPE, out type);
-				_editor.send_script(UnitPreviewApi.set_preview_resource((string)type, (string)name));
-				_editor.send(DeviceApi.frame());
+				_resource_preview.send_script(UnitPreviewApi.set_preview_resource((string)type, (string)name));
+				_resource_preview.send(DeviceApi.frame());
 			}
 		}
 	}

+ 1 - 1
tools/widgets/resource_chooser_button.vala

@@ -76,7 +76,7 @@ public class ResourceChooserButton : Gtk.Box
 			, null
 			);
 
-		var rb = new ResourceChooser(null, _project_store, false);
+		var rb = new ResourceChooser(null, _project_store);
 		rb.set_type_filter(type_filter);
 		rb.resource_selected.connect(() => { _name.text = rb._name; dg.response(ResponseType.OK); });