From 031e6ec5d849b42bd1523f46661b114d3c9652c4 Mon Sep 17 00:00:00 2001 From: rwilliaise Date: Fri, 30 Dec 2022 22:25:42 -0800 Subject: [PATCH 1/4] Add drag n drop functionality for maps --- .gitignore | 5 +- SConstruct | 4 + addons/tbloader/src/plugin.gd | 6 ++ src/builder.cpp | 19 ++-- src/builder.h | 2 + src/main.cpp | 14 ++- src/map_import.cpp | 179 ++++++++++++++++++++++++++++++++++ src/map_import.h | 43 ++++++++ 8 files changed, 261 insertions(+), 11 deletions(-) create mode 100644 src/map_import.cpp create mode 100644 src/map_import.h diff --git a/.gitignore b/.gitignore index 4cfc577..56d3fb5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ bin/ *.obj *.os .DS_Store -.vscode \ No newline at end of file +.vscode + +# clangd +compile_commands.json diff --git a/SConstruct b/SConstruct index 81c4b21..10938a4 100644 --- a/SConstruct +++ b/SConstruct @@ -18,6 +18,10 @@ sources = Glob("src/*.cpp") sources += Glob("src/builders/*.cpp") sources += Glob("src/map/*.cpp") +# clangd +env.Tool("compilation_db") +Alias("cdb", env.CompilationDatabase()) + if env["platform"] == "windows" and env["target"] == "template_debug": env.Append(LINKFLAGS=["/DEBUG"]) diff --git a/addons/tbloader/src/plugin.gd b/addons/tbloader/src/plugin.gd index 6d724da..fd2c3fb 100644 --- a/addons/tbloader/src/plugin.gd +++ b/addons/tbloader/src/plugin.gd @@ -5,6 +5,8 @@ class_name TBPlugin var map_control: Control = null var editing_loader: WeakRef = weakref(null) +var import_plugin: TBMapImportPlugin = TBMapImportPlugin.new() + func _enter_tree(): set_icons(true) @@ -12,6 +14,8 @@ func _enter_tree(): map_control.set_visible(false) add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, map_control) + add_import_plugin(import_plugin) + func _exit_tree(): set_icons(false) @@ -19,6 +23,8 @@ func _exit_tree(): map_control.queue_free() map_control = null + remove_import_plugin(import_plugin) + func _handles(object): return object is TBLoader diff --git a/src/builder.cpp b/src/builder.cpp index e1cfd60..93b613b 100644 --- a/src/builder.cpp +++ b/src/builder.cpp @@ -22,6 +22,11 @@ Builder::~Builder() { } +Node *Builder::get_owner() const +{ + return m_loader->get_owner() == nullptr ? m_loader : m_loader->get_owner(); +} + void Builder::load_map(const String& path) { UtilityFunctions::print("Building map ", path); @@ -71,7 +76,7 @@ void Builder::build_worldspawn(int idx, LMEntity& ent) // Create node for this entity auto container_node = memnew(Node3D()); m_loader->add_child(container_node); - container_node->set_owner(m_loader->get_owner()); + container_node->set_owner(get_owner()); // Decide generated collision type ColliderType collider = ColliderType::None; @@ -164,7 +169,7 @@ void Builder::build_entity_custom(int idx, LMEntity& ent, LMEntityGeometry& geo, auto instance = scene->instantiate(); m_loader->add_child(instance); - instance->set_owner(m_loader->get_owner()); + instance->set_owner(get_owner()); if (instance->is_class("Node3D")) { set_entity_node_common((Node3D*)instance, ent); @@ -236,7 +241,7 @@ void Builder::build_entity_light(int idx, LMEntity& ent) light->set_color(Color(color.x / 255.0f, color.y / 255.0f, color.z / 255.0f)); m_loader->add_child(light); - light->set_owner(m_loader->get_owner()); + light->set_owner(get_owner()); } void Builder::build_entity_area(int idx, LMEntity& ent) @@ -266,7 +271,7 @@ void Builder::build_entity_area(int idx, LMEntity& ent) // Create the area auto area = memnew(Area3D()); m_loader->add_child(area); - area->set_owner(m_loader->get_owner()); + area->set_owner(get_owner()); area->set_position(center); // Create collision shape for the area @@ -387,7 +392,7 @@ void Builder::add_collider_from_mesh(Node3D* node, Ref& mesh, Collide auto collision_shape = memnew(CollisionShape3D()); collision_shape->set_shape(mesh_shape); node->add_child(collision_shape, true); - collision_shape->set_owner(m_loader->get_owner()); + collision_shape->set_owner(get_owner()); } void Builder::add_surface_to_mesh(Ref& mesh, LMSurface& surf) @@ -439,7 +444,7 @@ MeshInstance3D* Builder::build_entity_mesh(int idx, LMEntity& ent, Node3D* paren // Set the layers that the mesh instance will be rendered in mesh_instance->set_layer_mask(m_loader->get_visual_layer_mask()); - mesh_instance->set_owner(m_loader->get_owner()); + mesh_instance->set_owner(get_owner()); mesh_instance->set_name(instance_name); // Create mesh @@ -529,7 +534,7 @@ MeshInstance3D* Builder::build_entity_mesh(int idx, LMEntity& ent, Node3D* paren StaticBody3D* static_body = memnew(StaticBody3D()); static_body->set_name(String(mesh_instance->get_name()) + "_col"); parent->add_child(static_body, true); - static_body->set_owner(m_loader->get_owner()); + static_body->set_owner(get_owner()); add_collider_from_mesh(static_body, collision_mesh, colshape); break; } diff --git a/src/builder.h b/src/builder.h index 3238a00..761b3bb 100644 --- a/src/builder.h +++ b/src/builder.h @@ -77,4 +77,6 @@ class Builder String material_path(const char* name); Ref texture_from_name(const char* name); Ref material_from_name(const char* name); + + Node *get_owner() const; }; diff --git a/src/main.cpp b/src/main.cpp index 1c1901b..51be8da 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,15 +4,23 @@ #include #include +#include using namespace godot; void register_tbloader_types(ModuleInitializationLevel p_level) { - if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { - return; + switch (p_level) + { + case MODULE_INITIALIZATION_LEVEL_EDITOR: + ClassDB::register_class(); + break; + case MODULE_INITIALIZATION_LEVEL_SCENE: + ClassDB::register_class(); + break; + default: + break; } - ClassDB::register_class(); } void unregister_tbloader_types(ModuleInitializationLevel p_level) diff --git a/src/map_import.cpp b/src/map_import.cpp new file mode 100644 index 0000000..8989377 --- /dev/null +++ b/src/map_import.cpp @@ -0,0 +1,179 @@ + +#include "gdextension_interface.h" +#include "godot_cpp/classes/editor_import_plugin.hpp" +#include "godot_cpp/core/error_macros.hpp" +#include "godot_cpp/variant/utility_functions.hpp" +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +TBMapImportPlugin::TBMapImportPlugin() +{ +} + +TBMapImportPlugin::~TBMapImportPlugin() +{ +} + +String TBMapImportPlugin::_get_save_extension() const +{ + return "scn"; +} + +String TBMapImportPlugin::_get_importer_name() const +{ + return "tbloader.map"; +} + +String TBMapImportPlugin::_get_resource_type() const +{ + return "PackedScene"; +} + +String TBMapImportPlugin::_get_visible_name() const +{ + return "Map"; +} + +bool TBMapImportPlugin::_get_option_visibility(const String &path, const StringName &option_name, const Dictionary &options) const +{ + return true; +} + +double TBMapImportPlugin::_get_priority() const +{ + return 1.0; +} + +int64_t TBMapImportPlugin::_get_import_order() const +{ + return IMPORT_ORDER_SCENE - 1; // after textures, before scenes +} + +template +inline Dictionary assemble_import_option(String name, PropertyHint type, String hint, N default_value) +{ + Dictionary dictionary; + dictionary["name"] = name; + dictionary["hint_string"] = hint; + dictionary["property_hint"] = type; + dictionary["default_value"] = default_value; + return dictionary; +} + +template +inline Dictionary assemble_import_option(String name, N default_value) +{ + Dictionary dictionary; + dictionary["name"] = name; + dictionary["default_value"] = default_value; + return dictionary; +} + +inline Dictionary assemble_import_option_category(String name) +{ + Dictionary dictionary; + dictionary["name"] = name; + dictionary["default_value"] = ""; + dictionary["usage"] = PROPERTY_USAGE_CATEGORY; + return dictionary; +} + +TypedArray TBMapImportPlugin::_get_import_options(const String &path, int64_t preset_index) const +{ + bool quake = preset_index == 1; + TypedArray out; + + out.append(assemble_import_option_category("map")); + out.append(assemble_import_option("inverse_scale", 16)); + + out.append(assemble_import_option_category("lighting")); + out.append(assemble_import_option("unwrap_uv2", false)); + + out.append(assemble_import_option_category("options")); + out.append(assemble_import_option("collisions_enabled", true)); + out.append(assemble_import_option("skip_hidden_layers", true)); + out.append(assemble_import_option("nearest_texture_filter", quake)); + out.append(assemble_import_option("clip_texture_path", PROPERTY_HINT_ENUM_SUGGESTION, "special/clip,tools/toolsclip", quake ? "special/clip" : "")); + out.append(assemble_import_option("skip_texture_path", PROPERTY_HINT_ENUM_SUGGESTION, "special/skip,tools/toolsskip", quake ? "special/skip" : "")); + out.append(assemble_import_option("visual_layer_mask", PROPERTY_HINT_LAYERS_3D_RENDER, "", 1)); + + out.append(assemble_import_option_category("entities")); + out.append(assemble_import_option("common_entities", true)); + out.append(assemble_import_option("entities_folder_path", PROPERTY_HINT_DIR, "", "res://entities")); + out.append(assemble_import_option("textures_folder_path", PROPERTY_HINT_DIR, "", "res://textures")); + + return out; +} + +int64_t TBMapImportPlugin::_get_preset_count() const +{ + return 2; +} + +String TBMapImportPlugin::_get_preset_name(int64_t preset_index) const +{ + switch (preset_index) + { + case 0: + return "Default"; + case 1: + return "Quake"; + default: + return "Unknown"; + } +} + +PackedStringArray TBMapImportPlugin::_get_recognized_extensions() const +{ + PackedStringArray array; + array.append("map"); + return array; +} + +int64_t TBMapImportPlugin::_import(const String &source_file, const String &save_path, const Dictionary &options, const TypedArray &platform_variants, const TypedArray &gen_files) const +{ + Ref scene = memnew(PackedScene); + + TBLoader *loader = memnew(TBLoader); + loader->set_name(source_file.get_file()); + + // Map + loader->set_map(source_file); + loader->set_inverse_scale(options["inverse_scale"]); + + // Lighting + loader->set_lighting_unwrap_uv2(options["unwrap_uv2"]); + + // Options + loader->set_collision(options["collisions_enabled"]); + loader->set_skip_hidden_layers(options["skip_hidden_layers"]); + loader->set_filter_nearest(options["nearest_texture_filter"]); + loader->set_clip_texture_name(options["clip_texture_path"]); + loader->set_skip_texture_name(options["skip_texture_path"]); + loader->set_visual_layer_mask(options["visual_layer_mask"]); + + // Entities + loader->set_entity_common(options["common_entities"]); + loader->set_entity_path(options["entities_folder_path"]); + loader->set_texture_path(options["textures_folder_path"]); + + loader->build_meshes(); + scene->pack(loader); + + auto save_path_formatted = save_path + String(".scn"); + int64_t err = ResourceSaver::get_singleton()->save(scene, save_path_formatted); + + ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + save_path_formatted + "'."); + return err; +} + diff --git a/src/map_import.h b/src/map_import.h new file mode 100644 index 0000000..de8bddd --- /dev/null +++ b/src/map_import.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include +#include + +#include +#include + +using namespace godot; + +class TBMapImportPlugin : public EditorImportPlugin +{ + GDCLASS(TBMapImportPlugin, EditorImportPlugin); + +protected: + static void _bind_methods() {} + +public: + + TBMapImportPlugin(); + ~TBMapImportPlugin(); + + virtual String _get_save_extension() const override; + virtual String _get_importer_name() const override; + virtual String _get_resource_type() const override; + virtual String _get_visible_name() const override; + + virtual bool _get_option_visibility(const String &path, const StringName &option_name, const Dictionary &options) const override; + + virtual double _get_priority() const override; + virtual int64_t _get_import_order() const override; + + virtual TypedArray _get_import_options(const String &path, int64_t preset_index) const override; + virtual int64_t _get_preset_count() const override; + virtual String _get_preset_name(int64_t preset_index) const override; + + virtual PackedStringArray _get_recognized_extensions() const override; + + virtual int64_t _import(const String &source_file, const String &save_path, const Dictionary &options, const TypedArray &platform_variants, const TypedArray &gen_files) const override; +}; + From 3cdd7c26563733ac3787328756b5dfd3634766c9 Mon Sep 17 00:00:00 2001 From: rwilliaise Date: Sun, 1 Jan 2023 20:34:13 -0800 Subject: [PATCH 2/4] Fix map import shenannigans --- addons/tbloader/src/plugin.gd | 8 +++++++- src/map_import.cpp | 8 ++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/addons/tbloader/src/plugin.gd b/addons/tbloader/src/plugin.gd index fd2c3fb..be5f851 100644 --- a/addons/tbloader/src/plugin.gd +++ b/addons/tbloader/src/plugin.gd @@ -46,7 +46,13 @@ func create_map_control() -> Control: func build_meshes(): var loader = editing_loader.get_ref() - loader.build_meshes() + if loader.get_scene_file_path() != null: # from imported + var interface = get_editor_interface() + var fs = interface.get_resource_filesystem() + fs.reimport_files([loader.get_scene_file_path()]) + interface.reload_scene_from_path(loader.get_tree().edited_scene_root.get_scene_file_path()) + else: + loader.build_meshes() func set_icons(on): var editor_interface = get_editor_interface() diff --git a/src/map_import.cpp b/src/map_import.cpp index 8989377..c28330b 100644 --- a/src/map_import.cpp +++ b/src/map_import.cpp @@ -1,10 +1,9 @@ -#include "gdextension_interface.h" -#include "godot_cpp/classes/editor_import_plugin.hpp" -#include "godot_cpp/core/error_macros.hpp" -#include "godot_cpp/variant/utility_functions.hpp" +#include +#include #include +#include #include #include #include @@ -12,6 +11,7 @@ #include #include #include +#include #include #include From 5908715649698ba5929c45e2527fdeed02101660 Mon Sep 17 00:00:00 2001 From: rwilliaise Date: Sun, 1 Jan 2023 21:16:58 -0800 Subject: [PATCH 3/4] Fix import categories --- src/map_import.cpp | 57 ++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/src/map_import.cpp b/src/map_import.cpp index c28330b..e66e78f 100644 --- a/src/map_import.cpp +++ b/src/map_import.cpp @@ -79,38 +79,25 @@ inline Dictionary assemble_import_option(String name, N default_value) return dictionary; } -inline Dictionary assemble_import_option_category(String name) -{ - Dictionary dictionary; - dictionary["name"] = name; - dictionary["default_value"] = ""; - dictionary["usage"] = PROPERTY_USAGE_CATEGORY; - return dictionary; -} - TypedArray TBMapImportPlugin::_get_import_options(const String &path, int64_t preset_index) const { bool quake = preset_index == 1; TypedArray out; - out.append(assemble_import_option_category("map")); - out.append(assemble_import_option("inverse_scale", 16)); + out.append(assemble_import_option("map/inverse_scale", 16)); - out.append(assemble_import_option_category("lighting")); - out.append(assemble_import_option("unwrap_uv2", false)); + out.append(assemble_import_option("lighting/unwrap_uv2", false)); - out.append(assemble_import_option_category("options")); - out.append(assemble_import_option("collisions_enabled", true)); - out.append(assemble_import_option("skip_hidden_layers", true)); - out.append(assemble_import_option("nearest_texture_filter", quake)); - out.append(assemble_import_option("clip_texture_path", PROPERTY_HINT_ENUM_SUGGESTION, "special/clip,tools/toolsclip", quake ? "special/clip" : "")); - out.append(assemble_import_option("skip_texture_path", PROPERTY_HINT_ENUM_SUGGESTION, "special/skip,tools/toolsskip", quake ? "special/skip" : "")); - out.append(assemble_import_option("visual_layer_mask", PROPERTY_HINT_LAYERS_3D_RENDER, "", 1)); + out.append(assemble_import_option("options/collisions_enabled", true)); + out.append(assemble_import_option("options/skip_hidden_layers", true)); + out.append(assemble_import_option("options/nearest_texture_filter", quake)); + out.append(assemble_import_option("options/clip_texture_path", PROPERTY_HINT_ENUM_SUGGESTION, "special/clip,tools/toolsclip", quake ? "special/clip" : "")); + out.append(assemble_import_option("options/skip_texture_path", PROPERTY_HINT_ENUM_SUGGESTION, "special/skip,tools/toolsskip", quake ? "special/skip" : "")); + out.append(assemble_import_option("options/visual_layer_mask", PROPERTY_HINT_LAYERS_3D_RENDER, "", 1)); - out.append(assemble_import_option_category("entities")); - out.append(assemble_import_option("common_entities", true)); - out.append(assemble_import_option("entities_folder_path", PROPERTY_HINT_DIR, "", "res://entities")); - out.append(assemble_import_option("textures_folder_path", PROPERTY_HINT_DIR, "", "res://textures")); + out.append(assemble_import_option("entities/common_entities", true)); + out.append(assemble_import_option("entities/entities_folder_path", PROPERTY_HINT_DIR, "", "res://entities")); + out.append(assemble_import_option("entities/textures_folder_path", PROPERTY_HINT_DIR, "", "res://textures")); return out; } @@ -149,23 +136,23 @@ int64_t TBMapImportPlugin::_import(const String &source_file, const String &save // Map loader->set_map(source_file); - loader->set_inverse_scale(options["inverse_scale"]); + loader->set_inverse_scale(options["map/inverse_scale"]); // Lighting - loader->set_lighting_unwrap_uv2(options["unwrap_uv2"]); + loader->set_lighting_unwrap_uv2(options["lighting/unwrap_uv2"]); // Options - loader->set_collision(options["collisions_enabled"]); - loader->set_skip_hidden_layers(options["skip_hidden_layers"]); - loader->set_filter_nearest(options["nearest_texture_filter"]); - loader->set_clip_texture_name(options["clip_texture_path"]); - loader->set_skip_texture_name(options["skip_texture_path"]); - loader->set_visual_layer_mask(options["visual_layer_mask"]); + loader->set_collision(options["options/collisions_enabled"]); + loader->set_skip_hidden_layers(options["options/skip_hidden_layers"]); + loader->set_filter_nearest(options["options/nearest_texture_filter"]); + loader->set_clip_texture_name(options["options/clip_texture_path"]); + loader->set_skip_texture_name(options["options/skip_texture_path"]); + loader->set_visual_layer_mask(options["options/visual_layer_mask"]); // Entities - loader->set_entity_common(options["common_entities"]); - loader->set_entity_path(options["entities_folder_path"]); - loader->set_texture_path(options["textures_folder_path"]); + loader->set_entity_common(options["entities/common_entities"]); + loader->set_entity_path(options["entities/entities_folder_path"]); + loader->set_texture_path(options["entities/textures_folder_path"]); loader->build_meshes(); scene->pack(loader); From 1365f0a5a077f79c002583094cb61a3e03cf3959 Mon Sep 17 00:00:00 2001 From: lego man <12103838+rwilliaise@users.noreply.github.com> Date: Mon, 2 Jan 2023 16:34:54 -0800 Subject: [PATCH 4/4] Remove `compile_commands.json` generation --- .gitignore | 5 +---- SConstruct | 4 ---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 56d3fb5..4cfc577 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,4 @@ bin/ *.obj *.os .DS_Store -.vscode - -# clangd -compile_commands.json +.vscode \ No newline at end of file diff --git a/SConstruct b/SConstruct index 10938a4..81c4b21 100644 --- a/SConstruct +++ b/SConstruct @@ -18,10 +18,6 @@ sources = Glob("src/*.cpp") sources += Glob("src/builders/*.cpp") sources += Glob("src/map/*.cpp") -# clangd -env.Tool("compilation_db") -Alias("cdb", env.CompilationDatabase()) - if env["platform"] == "windows" and env["target"] == "template_debug": env.Append(LINKFLAGS=["/DEBUG"])