Ver código fonte

Move source dir scanning to Project

Daniele Bartolini 9 anos atrás
pai
commit
bebfbecf0e

+ 10 - 1
samples/core/editors/unit_preview/unit_preview.lua

@@ -48,7 +48,16 @@ function UnitPreview:shutdown()
 	Device.destroy_world(self._world)
 end
 
-function UnitPreview:set_preview_unit(unit)
+function UnitPreview:set_preview_resource(type, name)
+	local unit = nil
+	if type == "unit" then
+		unit = name
+	elseif type == "sound" then
+		unit = "core/units/sound"
+	else
+		return
+	end
+
 	if self._unit_name == unit then
 		return
 	end

+ 2 - 2
tools/api/level_editor_api.vala

@@ -213,9 +213,9 @@ namespace Crown
 				);
 		}
 
-		public string set_placeable(PlaceableType type, string name)
+		public string set_placeable(string type, string name)
 		{
-			return "LevelEditor:set_placeable(\"%s\", \"%s\")".printf((type == PlaceableType.UNIT ? "unit" : "sound"), name);
+			return "LevelEditor:set_placeable(\"%s\", \"%s\")".printf(type, name);
 		}
 
 		public string selection_set(Guid[] ids)

+ 2 - 8
tools/api/unit_preview_api.vala

@@ -7,15 +7,9 @@ namespace Crown
 {
 	namespace UnitPreviewApi
 	{
-		const string[] _placeables =
+		public string set_preview_resource(string placeable_type, string name)
 		{
-			"unknown",
-			"core/units/sound",
-		};
-
-		public string set_preview_unit(PlaceableType placeable_type, string name)
-		{
-			return "UnitPreview:set_preview_unit(\"%s\")".printf(placeable_type == PlaceableType.UNIT ? name : _placeables[(int)placeable_type]);
+			return "UnitPreview:set_preview_resource(\"%s\", \"%s\")".printf(placeable_type, name);
 		}
 	}
 }

+ 11 - 17
tools/level_editor/level_editor.vala

@@ -29,12 +29,6 @@ namespace Crown
 		WORLD
 	}
 
-	public enum PlaceableType
-	{
-		UNIT,
-		SOUND
-	}
-
 	public class LevelEditor : Gtk.Window
 	{
 		private Project _project;
@@ -340,9 +334,9 @@ namespace Crown
 			this.show_all();
 		}
 
-		private void on_resource_browser_resource_selected(PlaceableType placeable_type, string name)
+		private void on_resource_browser_resource_selected(string type, string name)
 		{
-			_engine.send_script(LevelEditorApi.set_placeable(placeable_type, name));
+			_engine.send_script(LevelEditorApi.set_placeable(type, name));
 		}
 
 		private void on_compiler_connected()
@@ -977,49 +971,49 @@ namespace Crown
 
 		private void on_create_cube(Gtk.Action action)
 		{
-			_engine.send_script(LevelEditorApi.set_placeable(PlaceableType.UNIT, "core/units/primitives/cube"));
+			_engine.send_script(LevelEditorApi.set_placeable("unit", "core/units/primitives/cube"));
 		}
 
 		private void on_create_sphere(Gtk.Action action)
 		{
-			_engine.send_script(LevelEditorApi.set_placeable(PlaceableType.UNIT, "core/units/primitives/sphere"));
+			_engine.send_script(LevelEditorApi.set_placeable("unit", "core/units/primitives/sphere"));
 		}
 
 		private void on_create_cone(Gtk.Action action)
 		{
-			_engine.send_script(LevelEditorApi.set_placeable(PlaceableType.UNIT, "core/units/primitives/cone"));
+			_engine.send_script(LevelEditorApi.set_placeable("unit", "core/units/primitives/cone"));
 		}
 
 		private void on_create_cylinder(Gtk.Action action)
 		{
-			_engine.send_script(LevelEditorApi.set_placeable(PlaceableType.UNIT, "core/units/primitives/cylinder"));
+			_engine.send_script(LevelEditorApi.set_placeable("unit", "core/units/primitives/cylinder"));
 		}
 
 		private void on_create_plane(Gtk.Action action)
 		{
-			_engine.send_script(LevelEditorApi.set_placeable(PlaceableType.UNIT, "core/units/primitives/plane"));
+			_engine.send_script(LevelEditorApi.set_placeable("unit", "core/units/primitives/plane"));
 		}
 
 		private void on_create_camera(Gtk.Action action)
 		{
-			_engine.send_script(LevelEditorApi.set_placeable(PlaceableType.UNIT, "core/units/camera"));
+			_engine.send_script(LevelEditorApi.set_placeable("unit", "core/units/camera"));
 		}
 
 		private void on_create_light(Gtk.Action action)
 		{
-			_engine.send_script(LevelEditorApi.set_placeable(PlaceableType.UNIT, "core/units/light"));
+			_engine.send_script(LevelEditorApi.set_placeable("unit", "core/units/light"));
 		}
 
 		private void on_create_sound_source(Gtk.Action action)
 		{
-			_engine.send_script(LevelEditorApi.set_placeable(PlaceableType.SOUND, ""));
+			_engine.send_script(LevelEditorApi.set_placeable("sound", ""));
 		}
 
 		private void on_resource_browser(Gtk.Action action)
 		{
 			if (_resource_browser == null)
 			{
-				_resource_browser = new ResourceBrowser(_project.source_dir(), _project.data_dir());
+				_resource_browser = new ResourceBrowser(_project);
 				_resource_browser.relative_to = _toolbar;
 				_resource_browser.resource_selected.connect(on_resource_browser_resource_selected);
 				_resource_browser.delete_event.connect(() => { _resource_browser.hide(); return true; });

+ 53 - 0
tools/level_editor/project.vala

@@ -13,12 +13,16 @@ namespace Crown
 		private string _data_dir;
 		private string _platform;
 
+		private Database _files;
+
 		public Project()
 		{
 			_source_dir = null;
 			_toolchain_dir = null;
 			_data_dir = null;
 			_platform = "linux";
+
+			_files = new Database();
 		}
 
 		public void load(string source_dir, string toolchain_dir, string data_dir)
@@ -26,6 +30,8 @@ namespace Crown
 			_source_dir = source_dir;
 			_toolchain_dir = toolchain_dir;
 			_data_dir = data_dir;
+
+			scan_source_dir();
 		}
 
 		public string source_dir()
@@ -47,5 +53,52 @@ namespace Crown
 		{
 			return _platform;
 		}
+
+		public Database files()
+		{
+			return _files;
+		}
+
+		private void scan_source_dir()
+		{
+			list_directory_entries(File.new_for_path(_source_dir));
+		}
+
+		private void list_directory_entries(File dir, Cancellable? cancellable = null) throws Error
+		{
+			FileEnumerator enumerator = dir.enumerate_children(GLib.FileAttribute.STANDARD_NAME
+				, FileQueryInfoFlags.NOFOLLOW_SYMLINKS
+				, cancellable
+				);
+
+			FileInfo info = null;
+			while (cancellable.is_cancelled () == false && ((info = enumerator.next_file (cancellable)) != null))
+			{
+				if (info.get_file_type () == FileType.DIRECTORY)
+				{
+					File subdir = dir.resolve_relative_path (info.get_name());
+					list_directory_entries(subdir, cancellable);
+				}
+				else
+				{
+					string path = dir.get_path() + "/" + info.get_name();
+					string path_rel = File.new_for_path(_source_dir).get_relative_path(File.new_for_path(path));
+					string name = path_rel.substring(0, path_rel.last_index_of("."));
+					string type = path_rel.substring(path_rel.last_index_of(".") + 1);
+
+					Guid id = Guid.new_guid();
+					_files.create(id);
+					_files.set_property(id, "path", path);
+					_files.set_property(id, "type", type);
+					_files.set_property(id, "name", name);
+					_files.add_to_set(GUID_ZERO, "data", id);
+				}
+			}
+
+			if (cancellable.is_cancelled ())
+			{
+				throw new IOError.CANCELLED("Operation was cancelled");
+			}
+		}
 	}
 }

+ 100 - 76
tools/level_editor/resource_browser.vala

@@ -4,16 +4,30 @@
  */
 
 using Gtk;
+using Gee;
 
 namespace Crown
 {
-	public class ResourceBrowser : Gtk.Popover
+	const string resource_types[] =
+	{
+		"unit",
+		"sound"
+	};
+
+	public bool is_type(string type)
 	{
-		// Project paths
-		private string _source_dir;
-		private string _data_dir;
+		for (int i = 0; i < resource_types.length; ++i)
+		{
+			if (resource_types[i] == type)
+				return true;
+		}
+		return false;
+	}
 
+	public class ResourceBrowser : Gtk.Popover
+	{
 		// Data
+		private Project _project;
 		private GLib.Subprocess _engine_process;
 		private ConsoleClient _console_client;
 
@@ -21,6 +35,7 @@ namespace Crown
 		private Gtk.Entry _filter_entry;
 		private Gtk.TreeStore _tree_store;
 		private Gtk.TreeModelFilter _tree_filter;
+		private Gtk.TreeModelSort _tree_sort;
 		private Gtk.TreeView _tree_view;
 		private Gtk.TreeSelection _tree_selection;
 		private Gtk.ScrolledWindow _scrolled_window;
@@ -29,15 +44,12 @@ namespace Crown
 		private EngineView _engine_view;
 
 		// Signals
-		public signal void resource_selected(PlaceableType placeable_type, string name);
+		public signal void resource_selected(string type, string name);
 
-		public ResourceBrowser(string source_dir, string data_dir)
+		public ResourceBrowser(Project project)
 		{
-			// Project paths
-			_source_dir = source_dir;
-			_data_dir = data_dir;
-
 			// Data
+			_project = project;
 			_console_client = new ConsoleClient();
 
 			// Widgets
@@ -48,16 +60,29 @@ namespace Crown
 			_filter_entry.changed.connect(on_filter_entry_text_changed);
 			_filter_entry.key_press_event.connect(on_filter_entry_key_pressed);
 
-			_tree_store = new Gtk.TreeStore(2, typeof(string), typeof(PlaceableType));
+			_tree_store = new Gtk.TreeStore(2, typeof(string), typeof(string));
+
 			_tree_filter = new Gtk.TreeModelFilter(_tree_store, null);
 			_tree_filter.set_visible_func(filter_tree);
 
+			_tree_sort = new Gtk.TreeModelSort.with_model(_tree_filter);
+			_tree_sort.set_default_sort_func((model, iter_a, iter_b) => {
+				Value id_a;
+				Value id_b;
+				model.get_value(iter_a, 0, out id_a);
+				model.get_value(iter_b, 0, out id_b);
+				return strcmp((string)id_a, (string)id_b);
+			});
+
 			_tree_view = new Gtk.TreeView();
 			_tree_view.insert_column_with_attributes(-1, "Name", new Gtk.CellRendererText(), "text", 0, null);
-			_tree_view.model = _tree_filter;
+			_tree_view.insert_column_with_attributes(-1, "Type", new Gtk.CellRendererText(), "text", 1, null); // Debug
+			_tree_view.model = _tree_sort;
 			_tree_view.headers_visible = false;
+			_tree_view.can_focus = false;
 			_tree_view.row_activated.connect(on_row_activated);
 			_tree_view.button_press_event.connect(on_button_pressed);
+			_tree_view.button_release_event.connect(on_button_released);
 
 			_tree_selection = _tree_view.get_selection();
 			_tree_selection.set_mode(Gtk.SelectionMode.BROWSE);
@@ -67,7 +92,17 @@ namespace Crown
 			_scrolled_window.add(_tree_view);
 			_scrolled_window.set_size_request(300, 400);
 
-			walk_directory_tree();
+			Database db = _project.files();
+			HashSet<Guid?> files = db.get_property(GUID_ZERO, "data") as HashSet<Guid?>;
+			files.foreach((id) => {
+				Gtk.TreeIter resource_iter;
+				_tree_store.append(out resource_iter, null);
+				string name = (string)db.get_property(id, "name");
+				string type = (string)db.get_property(id, "type");
+				_tree_store.set(resource_iter, 0, name, 1, type, -1);
+				return true;
+			});
+			_tree_filter.refilter();
 
 			_engine_view = new EngineView(_console_client, false);
 			_engine_view.realized.connect(on_engine_view_realized);
@@ -83,7 +118,8 @@ namespace Crown
 
 		private void on_row_activated(Gtk.TreePath path, TreeViewColumn column)
 		{
-			Gtk.TreePath child_path = _tree_filter.convert_path_to_child_path(path);
+			Gtk.TreePath filter_path = _tree_sort.convert_path_to_child_path(path);
+			Gtk.TreePath child_path = _tree_filter.convert_path_to_child_path(filter_path);
 			Gtk.TreeIter iter;
 			if (_tree_store.get_iter(out iter, child_path))
 			{
@@ -91,23 +127,22 @@ namespace Crown
 				Value type;
 				_tree_store.get_value(iter, 0, out name);
 				_tree_store.get_value(iter, 1, out type);
-				resource_selected((PlaceableType)type, (string)name);
+				resource_selected((string)type, (string)name);
 				this.hide();
 			}
 		}
 
 		private bool on_button_pressed(Gdk.EventButton ev)
 		{
-			int button = (int)ev.button;
-
-			if (button == 1)
+			if (ev.button == 1)
 			{
 				Gtk.TreePath path;
 				int cell_x;
 				int cell_y;
 				if (_tree_view.get_path_at_pos((int)ev.x, (int)ev.y, out path, null, out cell_x, out cell_y))
 				{
-					Gtk.TreePath child_path = _tree_filter.convert_path_to_child_path(path);
+					Gtk.TreePath filter_path = _tree_sort.convert_path_to_child_path(path);
+					Gtk.TreePath child_path = _tree_filter.convert_path_to_child_path(filter_path);
 					Gtk.TreeIter iter;
 					if (_tree_store.get_iter(out iter, child_path))
 					{
@@ -115,8 +150,7 @@ namespace Crown
 						Value type;
 						_tree_store.get_value(iter, 0, out name);
 						_tree_store.get_value(iter, 1, out type);
-						resource_selected((PlaceableType)type, (string)name);
-						this.hide();
+						resource_selected((string)type, (string)name);
 					}
 				}
 			}
@@ -124,6 +158,23 @@ namespace Crown
 			return false;
 		}
 
+		private bool on_button_released(Gdk.EventButton ev)
+		{
+			if (ev.button == 1)
+			{
+				Gtk.TreePath path;
+				int cell_x;
+				int cell_y;
+				if (_tree_view.get_path_at_pos((int)ev.x, (int)ev.y, out path, null, out cell_x, out cell_y))
+				{
+					if (_tree_view.get_selection().path_is_selected(path))
+						this.hide();
+				}
+			}
+
+			return false;
+		}
+
 		private void on_destroy()
 		{
 			if (_console_client.is_connected())
@@ -138,7 +189,7 @@ namespace Crown
 			string args[] =
 			{
 				ENGINE_EXE,
-				"--data-dir", _data_dir,
+				"--data-dir", _project.data_dir(),
 				"--boot-dir", UNIT_PREVIEW_BOOT_DIR,
 				"--parent-window", window_xid.to_string(),
 				"--console-port", "10002",
@@ -158,7 +209,10 @@ namespace Crown
 			}
 
 			while (!_console_client.is_connected())
+			{
 				_console_client.connect("127.0.0.1", 10002);
+				GLib.Thread.usleep(100*1000);
+			}
 
 			_tree_view.set_cursor(new Gtk.TreePath.first(), null, false);
 		}
@@ -179,56 +233,18 @@ namespace Crown
 		private bool filter_tree(Gtk.TreeModel model, Gtk.TreeIter iter)
 		{
 			Value name;
+			Value type;
 			model.get_value(iter, 0, out name);
+			model.get_value(iter, 1, out type);
 
-			if (_filter_entry.text == "")
-					 return true;
+			string name_str = (string)name;
+			string type_str = (string)type;
 
-			string text = (string)name;
-			if (text.index_of(_filter_entry.text) > -1)
-				return true;
-			else
-				return false;
-		}
-
-		private void walk_directory_tree()
-		{
-			_tree_view.model = null;
-			list_children(File.new_for_path(_source_dir));
-			_tree_view.model = _tree_filter;
-		}
-
-		private void list_children(File file, string space = "", Cancellable? cancellable = null) throws Error
-		{
-			FileEnumerator enumerator = file.enumerate_children ("standard::*", FileQueryInfoFlags.NOFOLLOW_SYMLINKS, cancellable);
-
-			FileInfo info = null;
-			while (cancellable.is_cancelled () == false && ((info = enumerator.next_file (cancellable)) != null)) {
-				if (info.get_file_type () == FileType.DIRECTORY)
-				{
-					File subdir = file.resolve_relative_path (info.get_name ());
-					list_children (subdir, space + " ", cancellable);
-				}
-				else
-				{
-					string path = file.get_path() + "/" + info.get_name();
-					string path_rel = File.new_for_path(_source_dir).get_relative_path(File.new_for_path(path));
-					string type = path_rel.substring(path_rel.last_index_of("."), path_rel.length - path_rel.last_index_of("."));
-					string name = path_rel.substring(0, path_rel.last_index_of("."));
-
-					if (type == ".unit" || type == ".sound")
-					{
-						Gtk.TreeIter resource_iter;
-						_tree_store.append(out resource_iter, null);
-						_tree_store.set(resource_iter, 0, name, 1, type == ".unit" ? PlaceableType.UNIT : PlaceableType.SOUND, -1);
-					}
-				}
-			}
-
-			if (cancellable.is_cancelled ())
-			{
-				throw new IOError.CANCELLED("Operation was cancelled");
-			}
+			return name_str != null
+				&& type_str != null
+				&& is_type(type_str)
+				&& (_filter_entry.text.length == 0 || name_str.index_of(_filter_entry.text) > -1)
+				;
 		}
 
 		private bool on_filter_entry_key_pressed(Gdk.EventKey ev)
@@ -240,21 +256,29 @@ namespace Crown
 			if (ev.keyval == Gdk.Key.Down)
 			{
 				if (selected && model.iter_next(ref iter))
+				{
 					_tree_selection.select_iter(iter);
+					_tree_view.scroll_to_cell(model.get_path(iter), null, true, 1.0f, 0.0f);
+				}
 			}
 			else if (ev.keyval == Gdk.Key.Up)
 			{
 				if (selected && model.iter_previous(ref iter))
+				{
 					_tree_selection.select_iter(iter);
+					_tree_view.scroll_to_cell(model.get_path(iter), null, true, 1.0f, 0.0f);
+				}
 			}
 			else if (ev.keyval == 65293) // Enter
 			{
-				Value name;
-				Value type;
-				model.get_value(iter, 0, out name);
-				model.get_value(iter, 1, out type);
-				resource_selected((PlaceableType)type, (string)name);
-
+				if (selected)
+				{
+					Value name;
+					Value type;
+					model.get_value(iter, 0, out name);
+					model.get_value(iter, 1, out type);
+					resource_selected((string)type, (string)name);
+				}
 				this.hide();
 			}
 			else
@@ -273,7 +297,7 @@ namespace Crown
 				Value type;
 				model.get_value(iter, 0, out name);
 				model.get_value(iter, 1, out type);
-				_console_client.send_script(UnitPreviewApi.set_preview_unit((PlaceableType)type, (string)name));
+				_console_client.send_script(UnitPreviewApi.set_preview_resource((string)type, (string)name));
 			}
 		}
 	}