summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/import/resource_importer_scene.cpp173
-rw-r--r--editor/import/resource_importer_scene.h15
-rw-r--r--editor/plugins/mesh_instance_editor_plugin.cpp145
-rw-r--r--editor/plugins/mesh_instance_editor_plugin.h10
4 files changed, 277 insertions, 66 deletions
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 4ef8ec48a0..08d2897250 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -47,8 +47,6 @@
#include "scene/resources/ray_shape.h"
#include "scene/resources/sphere_shape.h"
-
-
uint32_t EditorSceneImporter::get_import_flags() const {
if (get_script_instance()) {
@@ -60,80 +58,73 @@ uint32_t EditorSceneImporter::get_import_flags() const {
void EditorSceneImporter::get_extensions(List<String> *r_extensions) const {
if (get_script_instance()) {
- Array arr= get_script_instance()->call("_get_extensions");
- for(int i=0;i<arr.size();i++) {
+ Array arr = get_script_instance()->call("_get_extensions");
+ for (int i = 0; i < arr.size(); i++) {
r_extensions->push_back(arr[i]);
}
return;
}
ERR_FAIL();
-
}
Node *EditorSceneImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
if (get_script_instance()) {
- return get_script_instance()->call("_import_scene",p_path,p_flags,p_bake_fps);
+ return get_script_instance()->call("_import_scene", p_path, p_flags, p_bake_fps);
}
ERR_FAIL_V(NULL);
-
}
-Ref<Animation> EditorSceneImporter::import_animation(const String &p_path, uint32_t p_flags,int p_bake_fps) {
+Ref<Animation> EditorSceneImporter::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) {
if (get_script_instance()) {
- return get_script_instance()->call("_import_animation",p_path,p_flags);
+ return get_script_instance()->call("_import_animation", p_path, p_flags);
}
ERR_FAIL_V(NULL);
-
}
//for documenters, these functions are useful when an importer calls an external conversion helper (like, fbx2gltf),
//and you want to load the resulting file
-Node* EditorSceneImporter::import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) {
-
- return ResourceImporterScene::get_singleton()->import_scene_from_other_importer(this,p_path,p_flags,p_bake_fps);
+Node *EditorSceneImporter::import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) {
+ return ResourceImporterScene::get_singleton()->import_scene_from_other_importer(this, p_path, p_flags, p_bake_fps);
}
Ref<Animation> EditorSceneImporter::import_animation_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps) {
- return ResourceImporterScene::get_singleton()->import_animation_from_other_importer(this,p_path,p_flags,p_bake_fps);
-
+ return ResourceImporterScene::get_singleton()->import_animation_from_other_importer(this, p_path, p_flags, p_bake_fps);
}
void EditorSceneImporter::_bind_methods() {
- ClassDB::bind_method(D_METHOD("import_scene_from_other_importer","path","flags","bake_fps"),&EditorSceneImporter::import_scene_from_other_importer);
- ClassDB::bind_method(D_METHOD("import_animation_from_other_importer","path","flags","bake_fps"),&EditorSceneImporter::import_animation_from_other_importer);
+ ClassDB::bind_method(D_METHOD("import_scene_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneImporter::import_scene_from_other_importer);
+ ClassDB::bind_method(D_METHOD("import_animation_from_other_importer", "path", "flags", "bake_fps"), &EditorSceneImporter::import_animation_from_other_importer);
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_import_flags"));
BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_extensions"));
- MethodInfo mi = MethodInfo(Variant::OBJECT, "_import_scene",PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps"));
- mi.return_val.class_name="Node";
+ MethodInfo mi = MethodInfo(Variant::OBJECT, "_import_scene", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps"));
+ mi.return_val.class_name = "Node";
BIND_VMETHOD(mi);
- mi = MethodInfo(Variant::OBJECT, "_import_animation",PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps"));
- mi.return_val.class_name="Animation";
+ mi = MethodInfo(Variant::OBJECT, "_import_animation", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"), PropertyInfo(Variant::INT, "bake_fps"));
+ mi.return_val.class_name = "Animation";
BIND_VMETHOD(mi);
- BIND_CONSTANT( IMPORT_SCENE );
- BIND_CONSTANT( IMPORT_ANIMATION );
- BIND_CONSTANT( IMPORT_ANIMATION_DETECT_LOOP );
- BIND_CONSTANT( IMPORT_ANIMATION_OPTIMIZE );
- BIND_CONSTANT( IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS );
- BIND_CONSTANT( IMPORT_ANIMATION_KEEP_VALUE_TRACKS );
- BIND_CONSTANT( IMPORT_GENERATE_TANGENT_ARRAYS );
- BIND_CONSTANT( IMPORT_FAIL_ON_MISSING_DEPENDENCIES );
- BIND_CONSTANT( IMPORT_MATERIALS_IN_INSTANCES );
- BIND_CONSTANT( IMPORT_USE_COMPRESSION );
-
+ BIND_CONSTANT(IMPORT_SCENE);
+ BIND_CONSTANT(IMPORT_ANIMATION);
+ BIND_CONSTANT(IMPORT_ANIMATION_DETECT_LOOP);
+ BIND_CONSTANT(IMPORT_ANIMATION_OPTIMIZE);
+ BIND_CONSTANT(IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
+ BIND_CONSTANT(IMPORT_ANIMATION_KEEP_VALUE_TRACKS);
+ BIND_CONSTANT(IMPORT_GENERATE_TANGENT_ARRAYS);
+ BIND_CONSTANT(IMPORT_FAIL_ON_MISSING_DEPENDENCIES);
+ BIND_CONSTANT(IMPORT_MATERIALS_IN_INSTANCES);
+ BIND_CONSTANT(IMPORT_USE_COMPRESSION);
}
-
/////////////////////////////////
void EditorScenePostImport::_bind_methods() {
@@ -201,6 +192,10 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const
return false;
}
+ if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) < 2) {
+ return false;
+ }
+
return true;
}
@@ -961,6 +956,36 @@ static String _make_extname(const String &p_str) {
return ext_name;
}
+void ResourceImporterScene::_find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Transform> &meshes) {
+
+ List<PropertyInfo> pi;
+ p_node->get_property_list(&pi);
+
+ MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
+
+ if (mi) {
+
+ Ref<ArrayMesh> mesh = mi->get_mesh();
+
+ if (mesh.is_valid() && !meshes.has(mesh)) {
+ Spatial *s = mi;
+ while (s->get_parent_spatial()) {
+ s = s->get_parent_spatial();
+ }
+
+ if (s == mi) {
+ meshes[mesh] = s->get_transform();
+ } else {
+ meshes[mesh] = s->get_transform() * mi->get_relative_transform(s);
+ }
+ }
+ }
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+
+ _find_meshes(p_node->get_child(i), meshes);
+ }
+}
+
void ResourceImporterScene::_make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_keep_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes) {
List<PropertyInfo> pi;
@@ -1140,7 +1165,8 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/compress"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files"), meshes_out ? 1 : 0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.05));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "external_files/store_in_subdir"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15));
@@ -1171,17 +1197,16 @@ void ResourceImporterScene::_replace_owner(Node *p_node, Node *p_scene, Node *p_
Node *n = p_node->get_child(i);
_replace_owner(n, p_scene, p_new_owner);
}
-
}
-Node* ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps) {
+Node *ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) {
Ref<EditorSceneImporter> importer;
String ext = p_path.get_extension().to_lower();
for (Set<Ref<EditorSceneImporter> >::Element *E = importers.front(); E; E = E->next()) {
- if (E->get().ptr()==p_exception)
+ if (E->get().ptr() == p_exception)
continue;
List<String> extensions;
E->get()->get_extensions(&extensions);
@@ -1199,42 +1224,41 @@ Node* ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporte
break;
}
- ERR_FAIL_COND_V(!importer.is_valid(),NULL);
+ ERR_FAIL_COND_V(!importer.is_valid(), NULL);
List<String> missing;
Error err;
- return importer->import_scene(p_path,p_flags,p_bake_fps,&missing,&err);
+ return importer->import_scene(p_path, p_flags, p_bake_fps, &missing, &err);
}
-Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps) {
-
+Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps) {
- Ref<EditorSceneImporter> importer;
- String ext = p_path.get_extension().to_lower();
+ Ref<EditorSceneImporter> importer;
+ String ext = p_path.get_extension().to_lower();
- for (Set<Ref<EditorSceneImporter> >::Element *E = importers.front(); E; E = E->next()) {
+ for (Set<Ref<EditorSceneImporter> >::Element *E = importers.front(); E; E = E->next()) {
- if (E->get().ptr()==p_exception)
- continue;
- List<String> extensions;
- E->get()->get_extensions(&extensions);
+ if (E->get().ptr() == p_exception)
+ continue;
+ List<String> extensions;
+ E->get()->get_extensions(&extensions);
- for (List<String>::Element *F = extensions.front(); F; F = F->next()) {
+ for (List<String>::Element *F = extensions.front(); F; F = F->next()) {
- if (F->get().to_lower() == ext) {
+ if (F->get().to_lower() == ext) {
- importer = E->get();
- break;
- }
- }
+ importer = E->get();
+ break;
+ }
+ }
- if (importer.is_valid())
- break;
- }
+ if (importer.is_valid())
+ break;
+ }
- ERR_FAIL_COND_V(!importer.is_valid(),NULL);
+ ERR_FAIL_COND_V(!importer.is_valid(), NULL);
- return importer->import_animation(p_path,p_flags,p_bake_fps);
+ return importer->import_animation(p_path, p_flags, p_bake_fps);
}
Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files) {
@@ -1371,6 +1395,37 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
}
}
+ if (light_bake_mode == 2 /* || generate LOD */) {
+
+ Map<Ref<ArrayMesh>, Transform> meshes;
+ _find_meshes(scene, meshes);
+
+ if (light_bake_mode == 2) {
+
+ float texel_size = p_options["meshes/lightmap_texel_size"];
+ texel_size = MAX(0.001, texel_size);
+
+ EditorProgress progress("gen_lightmaps", TTR("Generating Lightmaps"), meshes.size());
+ int step = 0;
+ for (Map<Ref<ArrayMesh>, Transform>::Element *E = meshes.front(); E; E = E->next()) {
+
+ Ref<ArrayMesh> mesh = E->key();
+ String name = mesh->get_name();
+ if (name == "") { //should not happen but..
+ name = "Mesh " + itos(step);
+ }
+
+ progress.step(TTR("Generating for Mesh: ") + name + " (" + itos(step) + "/" + itos(meshes.size()) + ")", step);
+
+ Error err = mesh->lightmap_unwrap(E->get(), texel_size);
+ if (err != OK) {
+ EditorNode::add_io_error("Mesh '" + name + "' failed lightmap generation. Please fix geometry.");
+ }
+ step++;
+ }
+ }
+ }
+
if (external_animations || external_materials || external_meshes) {
Map<Ref<Animation>, Ref<Animation> > anim_map;
Map<Ref<Material>, Ref<Material> > mat_map;
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index fc6ce05fa4..933585a48c 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -40,13 +40,13 @@ class Material;
class EditorSceneImporter : public Reference {
GDCLASS(EditorSceneImporter, Reference);
-protected:
+protected:
static void _bind_methods();
-
- Node* import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps);
+ Node *import_scene_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps);
Ref<Animation> import_animation_from_other_importer(const String &p_path, uint32_t p_flags, int p_bake_fps);
+
public:
enum ImportFlags {
IMPORT_SCENE = 1,
@@ -62,11 +62,10 @@ public:
};
-
virtual uint32_t get_import_flags() const;
virtual void get_extensions(List<String> *r_extensions) const;
virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL);
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags,int p_bake_fps);
+ virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps);
EditorSceneImporter() {}
};
@@ -136,6 +135,8 @@ public:
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const;
virtual int get_import_order() const { return 100; } //after everything
+ void _find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Transform> &meshes);
+
void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_keep_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes);
Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<ArrayMesh>, Ref<Shape> > &collision_map, LightBakeMode p_light_bake_mode);
@@ -147,8 +148,8 @@ public:
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL);
- Node* import_scene_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps);
- Ref<Animation> import_animation_from_other_importer(EditorSceneImporter *p_exception,const String &p_path, uint32_t p_flags, int p_bake_fps);
+ Node *import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps);
+ Ref<Animation> import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps);
ResourceImporterScene();
};
diff --git a/editor/plugins/mesh_instance_editor_plugin.cpp b/editor/plugins/mesh_instance_editor_plugin.cpp
index 84fc0cecf2..9d116349c0 100644
--- a/editor/plugins/mesh_instance_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_editor_plugin.cpp
@@ -195,7 +195,139 @@ void MeshInstanceEditor::_menu_option(int p_option) {
outline_dialog->popup_centered(Vector2(200, 90));
} break;
+ case MENU_OPTION_CREATE_UV2: {
+
+ Ref<ArrayMesh> mesh = node->get_mesh();
+ if (!mesh.is_valid()) {
+ err_dialog->set_text(TTR("Contained Mesh is not of type ArrayMesh."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
+ Error err = mesh->lightmap_unwrap(node->get_global_transform());
+ if (err != OK) {
+ err_dialog->set_text(TTR("UV Unwrap failed, mesh may not be manifold?"));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
+ } break;
+ case MENU_OPTION_DEBUG_UV1: {
+ Ref<Mesh> mesh = node->get_mesh();
+ if (!mesh.is_valid()) {
+ err_dialog->set_text(TTR("No mesh to debug."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+ _create_uv_lines(0);
+ } break;
+ case MENU_OPTION_DEBUG_UV2: {
+ Ref<Mesh> mesh = node->get_mesh();
+ if (!mesh.is_valid()) {
+ err_dialog->set_text(TTR("No mesh to debug."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+ _create_uv_lines(1);
+ } break;
+ }
+}
+
+struct MeshInstanceEditorEdgeSort {
+
+ Vector2 a;
+ Vector2 b;
+
+ bool operator<(const MeshInstanceEditorEdgeSort &p_b) const {
+ if (a == p_b.a)
+ return b < p_b.b;
+ else
+ return a < p_b.a;
+ }
+
+ MeshInstanceEditorEdgeSort() {}
+ MeshInstanceEditorEdgeSort(const Vector2 &p_a, const Vector2 &p_b) {
+ if (p_a < p_b) {
+ a = p_a;
+ b = p_b;
+ } else {
+ b = p_a;
+ a = p_b;
+ }
+ }
+};
+
+void MeshInstanceEditor::_create_uv_lines(int p_layer) {
+
+ Ref<Mesh> mesh = node->get_mesh();
+ ERR_FAIL_COND(!mesh.is_valid());
+
+ Set<MeshInstanceEditorEdgeSort> edges;
+ uv_lines.clear();
+ for (int i = 0; i < mesh->get_surface_count(); i++) {
+ if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES)
+ continue;
+ Array a = mesh->surface_get_arrays(i);
+
+ PoolVector<Vector2> uv = a[p_layer == 0 ? Mesh::ARRAY_TEX_UV : Mesh::ARRAY_TEX_UV2];
+ if (uv.size() == 0) {
+ err_dialog->set_text(TTR("Model has no UV in this layer"));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
+ PoolVector<Vector2>::Read r = uv.read();
+
+ PoolVector<int> indices = a[Mesh::ARRAY_INDEX];
+ PoolVector<int>::Read ri;
+
+ int ic;
+ bool use_indices;
+
+ if (indices.size()) {
+ ic = indices.size();
+ ri = indices.read();
+ use_indices = true;
+ } else {
+ ic = uv.size();
+ use_indices = false;
+ }
+
+ for (int j = 0; j < ic; j += 3) {
+
+ for (int k = 0; k < 3; k++) {
+
+ MeshInstanceEditorEdgeSort edge;
+ if (use_indices) {
+ edge.a = r[ri[j + k]];
+ edge.b = r[ri[j + ((k + 1) % 3)]];
+ } else {
+ edge.a = r[j + k];
+ edge.b = r[j + ((k + 1) % 3)];
+ }
+
+ if (edges.has(edge))
+ continue;
+
+ uv_lines.push_back(edge.a);
+ uv_lines.push_back(edge.b);
+ edges.insert(edge);
+ }
+ }
}
+
+ debug_uv_dialog->popup_centered_minsize();
+}
+
+void MeshInstanceEditor::_debug_uv_draw() {
+
+ if (uv_lines.size() == 0)
+ return;
+
+ debug_uv->set_clip_contents(true);
+ debug_uv->draw_rect(Rect2(Vector2(), debug_uv->get_size()), Color(0.2, 0.2, 0.0));
+ debug_uv->draw_set_transform(Vector2(), 0, debug_uv->get_size());
+ debug_uv->draw_multiline(uv_lines, Color(1.0, 0.8, 0.7));
}
void MeshInstanceEditor::_create_outline_mesh() {
@@ -244,6 +376,7 @@ void MeshInstanceEditor::_bind_methods() {
ClassDB::bind_method("_menu_option", &MeshInstanceEditor::_menu_option);
ClassDB::bind_method("_create_outline_mesh", &MeshInstanceEditor::_create_outline_mesh);
+ ClassDB::bind_method("_debug_uv_draw", &MeshInstanceEditor::_debug_uv_draw);
}
MeshInstanceEditor::MeshInstanceEditor() {
@@ -263,6 +396,10 @@ MeshInstanceEditor::MeshInstanceEditor() {
options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH);
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Create Outline Mesh.."), MENU_OPTION_CREATE_OUTLINE_MESH);
+ options->get_popup()->add_separator();
+ options->get_popup()->add_item(TTR("View UV1"), MENU_OPTION_DEBUG_UV1);
+ options->get_popup()->add_item(TTR("View UV2"), MENU_OPTION_DEBUG_UV2);
+ options->get_popup()->add_item(TTR("Unwrap UV2 for Lightmap/AO"), MENU_OPTION_CREATE_UV2);
options->get_popup()->connect("id_pressed", this, "_menu_option");
@@ -286,6 +423,14 @@ MeshInstanceEditor::MeshInstanceEditor() {
err_dialog = memnew(AcceptDialog);
add_child(err_dialog);
+
+ debug_uv_dialog = memnew(AcceptDialog);
+ debug_uv_dialog->set_title("UV Channel Debug");
+ add_child(debug_uv_dialog);
+ debug_uv = memnew(Control);
+ debug_uv->set_custom_minimum_size(Size2(600, 600) * EDSCALE);
+ debug_uv->connect("draw", this, "_debug_uv_draw");
+ debug_uv_dialog->add_child(debug_uv);
}
void MeshInstanceEditorPlugin::edit(Object *p_object) {
diff --git a/editor/plugins/mesh_instance_editor_plugin.h b/editor/plugins/mesh_instance_editor_plugin.h
index fa851458ce..68c149f98a 100644
--- a/editor/plugins/mesh_instance_editor_plugin.h
+++ b/editor/plugins/mesh_instance_editor_plugin.h
@@ -47,6 +47,9 @@ class MeshInstanceEditor : public Node {
MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE,
MENU_OPTION_CREATE_NAVMESH,
MENU_OPTION_CREATE_OUTLINE_MESH,
+ MENU_OPTION_CREATE_UV2,
+ MENU_OPTION_DEBUG_UV1,
+ MENU_OPTION_DEBUG_UV2,
};
MeshInstance *node;
@@ -58,11 +61,18 @@ class MeshInstanceEditor : public Node {
AcceptDialog *err_dialog;
+ AcceptDialog *debug_uv_dialog;
+ Control *debug_uv;
+ Vector<Vector2> uv_lines;
+
void _menu_option(int p_option);
void _create_outline_mesh();
+ void _create_uv_lines(int p_layer);
friend class MeshInstanceEditorPlugin;
+ void _debug_uv_draw();
+
protected:
void _node_removed(Node *p_node);
static void _bind_methods();