diff options
Diffstat (limited to 'editor')
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 173 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.h | 15 | ||||
-rw-r--r-- | editor/plugins/mesh_instance_editor_plugin.cpp | 145 | ||||
-rw-r--r-- | editor/plugins/mesh_instance_editor_plugin.h | 10 |
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(); |