summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/create_dialog.cpp48
-rw-r--r--editor/editor_export.cpp12
-rw-r--r--editor/editor_file_system.cpp372
-rw-r--r--editor/editor_resource_preview.cpp17
-rw-r--r--editor/export_template_manager.cpp3
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp11
-rw-r--r--editor/plugins/ot_features_plugin.cpp6
-rw-r--r--editor/plugins/script_editor_plugin.cpp22
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp267
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h21
-rw-r--r--editor/plugins/texture_editor_plugin.cpp2
11 files changed, 486 insertions, 295 deletions
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 50e1d03663..fbb61a1614 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -377,13 +377,15 @@ void CreateDialog::_confirmed() {
return;
}
- Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE);
- if (f.is_valid()) {
- f->store_line(selected_item);
-
- for (int i = 0; i < MIN(32, recent->get_item_count()); i++) {
- if (recent->get_item_text(i) != selected_item) {
- f->store_line(recent->get_item_text(i));
+ {
+ Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE);
+ if (f.is_valid()) {
+ f->store_line(selected_item);
+
+ for (int i = 0; i < MIN(32, recent->get_item_count()); i++) {
+ if (recent->get_item_text(i) != selected_item) {
+ f->store_line(recent->get_item_text(i));
+ }
}
}
}
@@ -645,23 +647,25 @@ void CreateDialog::_save_and_update_favorite_list() {
favorites->clear();
TreeItem *root = favorites->create_item();
- Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
- if (f.is_valid()) {
- for (int i = 0; i < favorite_list.size(); i++) {
- String l = favorite_list[i];
- String name = l.get_slicec(' ', 0);
- if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) {
- continue;
- }
- f->store_line(l);
+ {
+ Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
+ if (f.is_valid()) {
+ for (int i = 0; i < favorite_list.size(); i++) {
+ String l = favorite_list[i];
+ String name = l.get_slicec(' ', 0);
+ if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) {
+ continue;
+ }
+ f->store_line(l);
- if (_is_class_disabled_by_feature_profile(name)) {
- continue;
- }
+ if (_is_class_disabled_by_feature_profile(name)) {
+ continue;
+ }
- TreeItem *ti = favorites->create_item(root);
- ti->set_text(0, l);
- ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback));
+ TreeItem *ti = favorites->create_item(root);
+ ti->set_text(0, l);
+ ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback));
+ }
}
}
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index 40b850cace..58a9175df1 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -343,7 +343,8 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa
ftmp->store_buffer(p_data.ptr(), p_data.size());
if (fae.is_valid()) {
- fae->release();
+ ftmp.unref();
+ fae.unref();
}
int pad = _get_pad(PCK_PADDING, pd->f->get_position());
@@ -1142,6 +1143,10 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
Error err = export_project_files(p_preset, p_debug, _save_pack_file, &pd, _add_shared_object);
+ // Close temp file.
+ pd.f.unref();
+ ftmp.unref();
+
if (err != OK) {
DirAccess::remove_file_or_error(tmppath);
ERR_PRINT("Failed to export project files");
@@ -1269,7 +1274,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
}
if (fae.is_valid()) {
- fae->release();
+ fhead.unref();
+ fae.unref();
}
int header_padding = _get_pad(PCK_PADDING, f->get_position());
@@ -1301,6 +1307,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
f->store_buffer(buf, got);
}
+ ftmp.unref(); // Close temp file.
+
if (p_embed) {
// Ensure embedded data ends at a 64-bit multiple
uint64_t embed_end = f->get_position() - embed_pos + 12;
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 98bf5d3234..099dfe69d5 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -218,69 +218,71 @@ void EditorFileSystem::_scan_filesystem() {
String project = ProjectSettings::get_singleton()->get_resource_path();
String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME);
- Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::READ);
-
- bool first = true;
- if (f.is_valid()) {
- //read the disk cache
- while (!f->eof_reached()) {
- String l = f->get_line().strip_edges();
- if (first) {
- if (first_scan) {
- // only use this on first scan, afterwards it gets ignored
- // this is so on first reimport we synchronize versions, then
- // we don't care until editor restart. This is for usability mainly so
- // your workflow is not killed after changing a setting by forceful reimporting
- // everything there is.
- filesystem_settings_version_for_import = l.strip_edges();
- if (filesystem_settings_version_for_import != ResourceFormatImporter::get_singleton()->get_import_settings_hash()) {
- revalidate_import_files = true;
+ {
+ Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::READ);
+
+ bool first = true;
+ if (f.is_valid()) {
+ //read the disk cache
+ while (!f->eof_reached()) {
+ String l = f->get_line().strip_edges();
+ if (first) {
+ if (first_scan) {
+ // only use this on first scan, afterwards it gets ignored
+ // this is so on first reimport we synchronize versions, then
+ // we don't care until editor restart. This is for usability mainly so
+ // your workflow is not killed after changing a setting by forceful reimporting
+ // everything there is.
+ filesystem_settings_version_for_import = l.strip_edges();
+ if (filesystem_settings_version_for_import != ResourceFormatImporter::get_singleton()->get_import_settings_hash()) {
+ revalidate_import_files = true;
+ }
}
+ first = false;
+ continue;
+ }
+ if (l.is_empty()) {
+ continue;
}
- first = false;
- continue;
- }
- if (l.is_empty()) {
- continue;
- }
- if (l.begins_with("::")) {
- Vector<String> split = l.split("::");
- ERR_CONTINUE(split.size() != 3);
- String name = split[1];
+ if (l.begins_with("::")) {
+ Vector<String> split = l.split("::");
+ ERR_CONTINUE(split.size() != 3);
+ String name = split[1];
- cpath = name;
+ cpath = name;
- } else {
- Vector<String> split = l.split("::");
- ERR_CONTINUE(split.size() != 9);
- String name = split[0];
- String file;
-
- file = name;
- name = cpath.plus_file(name);
-
- FileCache fc;
- fc.type = split[1];
- fc.uid = split[2].to_int();
- fc.modification_time = split[3].to_int();
- fc.import_modification_time = split[4].to_int();
- fc.import_valid = split[5].to_int() != 0;
- fc.import_group_file = split[6].strip_edges();
- fc.script_class_name = split[7].get_slice("<>", 0);
- fc.script_class_extends = split[7].get_slice("<>", 1);
- fc.script_class_icon_path = split[7].get_slice("<>", 2);
-
- String deps = split[8].strip_edges();
- if (deps.length()) {
- Vector<String> dp = deps.split("<>");
- for (int i = 0; i < dp.size(); i++) {
- String path = dp[i];
- fc.deps.push_back(path);
+ } else {
+ Vector<String> split = l.split("::");
+ ERR_CONTINUE(split.size() != 9);
+ String name = split[0];
+ String file;
+
+ file = name;
+ name = cpath.plus_file(name);
+
+ FileCache fc;
+ fc.type = split[1];
+ fc.uid = split[2].to_int();
+ fc.modification_time = split[3].to_int();
+ fc.import_modification_time = split[4].to_int();
+ fc.import_valid = split[5].to_int() != 0;
+ fc.import_group_file = split[6].strip_edges();
+ fc.script_class_name = split[7].get_slice("<>", 0);
+ fc.script_class_extends = split[7].get_slice("<>", 1);
+ fc.script_class_icon_path = split[7].get_slice("<>", 2);
+
+ String deps = split[8].strip_edges();
+ if (deps.length()) {
+ Vector<String> dp = deps.split("<>");
+ for (int i = 0; i < dp.size(); i++) {
+ String path = dp[i];
+ fc.deps.push_back(path);
+ }
}
- }
- file_cache[name] = fc;
+ file_cache[name] = fc;
+ }
}
}
}
@@ -1700,74 +1702,77 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
for (const KeyValue<String, Map<StringName, Variant>> &E : source_file_options) {
const String &file = E.key;
String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(file);
- Ref<FileAccess> f = FileAccess::open(file + ".import", FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Cannot open import file '" + file + ".import'.");
-
- //write manually, as order matters ([remap] has to go first for performance).
- f->store_line("[remap]");
- f->store_line("");
- f->store_line("importer=\"" + importer->get_importer_name() + "\"");
- int version = importer->get_format_version();
- if (version > 0) {
- f->store_line("importer_version=" + itos(version));
- }
- if (!importer->get_resource_type().is_empty()) {
- f->store_line("type=\"" + importer->get_resource_type() + "\"");
- }
-
Vector<String> dest_paths;
+ {
+ Ref<FileAccess> f = FileAccess::open(file + ".import", FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Cannot open import file '" + file + ".import'.");
+
+ //write manually, as order matters ([remap] has to go first for performance).
+ f->store_line("[remap]");
+ f->store_line("");
+ f->store_line("importer=\"" + importer->get_importer_name() + "\"");
+ int version = importer->get_format_version();
+ if (version > 0) {
+ f->store_line("importer_version=" + itos(version));
+ }
+ if (!importer->get_resource_type().is_empty()) {
+ f->store_line("type=\"" + importer->get_resource_type() + "\"");
+ }
- if (err == OK) {
- String path = base_path + "." + importer->get_save_extension();
- f->store_line("path=\"" + path + "\"");
- dest_paths.push_back(path);
- }
-
- f->store_line("group_file=" + Variant(p_group_file).get_construct_string());
-
- if (err == OK) {
- f->store_line("valid=true");
- } else {
- f->store_line("valid=false");
- }
- f->store_line("[deps]\n");
+ if (err == OK) {
+ String path = base_path + "." + importer->get_save_extension();
+ f->store_line("path=\"" + path + "\"");
+ dest_paths.push_back(path);
+ }
- f->store_line("");
+ f->store_line("group_file=" + Variant(p_group_file).get_construct_string());
- f->store_line("source_file=" + Variant(file).get_construct_string());
- if (dest_paths.size()) {
- Array dp;
- for (int i = 0; i < dest_paths.size(); i++) {
- dp.push_back(dest_paths[i]);
+ if (err == OK) {
+ f->store_line("valid=true");
+ } else {
+ f->store_line("valid=false");
}
- f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
- }
- f->store_line("[params]");
- f->store_line("");
+ f->store_line("[deps]\n");
- //store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
+ f->store_line("");
- List<ResourceImporter::ImportOption> options;
- importer->get_import_options(file, &options);
- //set default values
- for (const ResourceImporter::ImportOption &F : options) {
- String base = F.option.name;
- Variant v = F.default_value;
- if (source_file_options[file].has(base)) {
- v = source_file_options[file][base];
+ f->store_line("source_file=" + Variant(file).get_construct_string());
+ if (dest_paths.size()) {
+ Array dp;
+ for (int i = 0; i < dest_paths.size(); i++) {
+ dp.push_back(dest_paths[i]);
+ }
+ f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
+ }
+ f->store_line("[params]");
+ f->store_line("");
+
+ //store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
+
+ List<ResourceImporter::ImportOption> options;
+ importer->get_import_options(file, &options);
+ //set default values
+ for (const ResourceImporter::ImportOption &F : options) {
+ String base = F.option.name;
+ Variant v = F.default_value;
+ if (source_file_options[file].has(base)) {
+ v = source_file_options[file][base];
+ }
+ String value;
+ VariantWriter::write_to_string(v, value);
+ f->store_line(base + "=" + value);
}
- String value;
- VariantWriter::write_to_string(v, value);
- f->store_line(base + "=" + value);
}
// Store the md5's of the various files. These are stored separately so that the .import files can be version controlled.
- Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(md5s.is_null(), ERR_FILE_CANT_OPEN, "Cannot open MD5 file '" + base_path + ".md5'.");
+ {
+ Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(md5s.is_null(), ERR_FILE_CANT_OPEN, "Cannot open MD5 file '" + base_path + ".md5'.");
- md5s->store_line("source_md5=\"" + FileAccess::get_md5(file) + "\"");
- if (dest_paths.size()) {
- md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+ md5s->store_line("source_md5=\"" + FileAccess::get_md5(file) + "\"");
+ if (dest_paths.size()) {
+ md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+ }
}
EditorFileSystemDirectory *fs = nullptr;
@@ -1914,100 +1919,103 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
//as import is complete, save the .import file
- Ref<FileAccess> f = FileAccess::open(p_file + ".import", FileAccess::WRITE);
- ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file from path '" + p_file + ".import'.");
-
- //write manually, as order matters ([remap] has to go first for performance).
- f->store_line("[remap]");
- f->store_line("");
- f->store_line("importer=\"" + importer->get_importer_name() + "\"");
- int version = importer->get_format_version();
- if (version > 0) {
- f->store_line("importer_version=" + itos(version));
- }
- if (!importer->get_resource_type().is_empty()) {
- f->store_line("type=\"" + importer->get_resource_type() + "\"");
- }
-
- if (uid == ResourceUID::INVALID_ID) {
- uid = ResourceUID::get_singleton()->create_id();
- }
+ Vector<String> dest_paths;
+ {
+ Ref<FileAccess> f = FileAccess::open(p_file + ".import", FileAccess::WRITE);
+ ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file from path '" + p_file + ".import'.");
- f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format
+ //write manually, as order matters ([remap] has to go first for performance).
+ f->store_line("[remap]");
+ f->store_line("");
+ f->store_line("importer=\"" + importer->get_importer_name() + "\"");
+ int version = importer->get_format_version();
+ if (version > 0) {
+ f->store_line("importer_version=" + itos(version));
+ }
+ if (!importer->get_resource_type().is_empty()) {
+ f->store_line("type=\"" + importer->get_resource_type() + "\"");
+ }
- Vector<String> dest_paths;
+ if (uid == ResourceUID::INVALID_ID) {
+ uid = ResourceUID::get_singleton()->create_id();
+ }
- if (err == OK) {
- if (importer->get_save_extension().is_empty()) {
- //no path
- } else if (import_variants.size()) {
- //import with variants
- for (const String &E : import_variants) {
- String path = base_path.c_escape() + "." + E + "." + importer->get_save_extension();
+ f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format
- f->store_line("path." + E + "=\"" + path + "\"");
+ if (err == OK) {
+ if (importer->get_save_extension().is_empty()) {
+ //no path
+ } else if (import_variants.size()) {
+ //import with variants
+ for (const String &E : import_variants) {
+ String path = base_path.c_escape() + "." + E + "." + importer->get_save_extension();
+
+ f->store_line("path." + E + "=\"" + path + "\"");
+ dest_paths.push_back(path);
+ }
+ } else {
+ String path = base_path + "." + importer->get_save_extension();
+ f->store_line("path=\"" + path + "\"");
dest_paths.push_back(path);
}
+
} else {
- String path = base_path + "." + importer->get_save_extension();
- f->store_line("path=\"" + path + "\"");
- dest_paths.push_back(path);
+ f->store_line("valid=false");
}
- } else {
- f->store_line("valid=false");
- }
+ if (metadata != Variant()) {
+ f->store_line("metadata=" + metadata.get_construct_string());
+ }
- if (metadata != Variant()) {
- f->store_line("metadata=" + metadata.get_construct_string());
- }
+ f->store_line("");
- f->store_line("");
+ f->store_line("[deps]\n");
- f->store_line("[deps]\n");
+ if (gen_files.size()) {
+ Array genf;
+ for (const String &E : gen_files) {
+ genf.push_back(E);
+ dest_paths.push_back(E);
+ }
- if (gen_files.size()) {
- Array genf;
- for (const String &E : gen_files) {
- genf.push_back(E);
- dest_paths.push_back(E);
+ String value;
+ VariantWriter::write_to_string(genf, value);
+ f->store_line("files=" + value);
+ f->store_line("");
}
- String value;
- VariantWriter::write_to_string(genf, value);
- f->store_line("files=" + value);
- f->store_line("");
- }
+ f->store_line("source_file=" + Variant(p_file).get_construct_string());
- f->store_line("source_file=" + Variant(p_file).get_construct_string());
-
- if (dest_paths.size()) {
- Array dp;
- for (int i = 0; i < dest_paths.size(); i++) {
- dp.push_back(dest_paths[i]);
+ if (dest_paths.size()) {
+ Array dp;
+ for (int i = 0; i < dest_paths.size(); i++) {
+ dp.push_back(dest_paths[i]);
+ }
+ f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
}
- f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
- }
- f->store_line("[params]");
- f->store_line("");
+ f->store_line("[params]");
+ f->store_line("");
- //store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
+ //store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
- for (const ResourceImporter::ImportOption &E : opts) {
- String base = E.option.name;
- String value;
- VariantWriter::write_to_string(params[base], value);
- f->store_line(base + "=" + value);
+ for (const ResourceImporter::ImportOption &E : opts) {
+ String base = E.option.name;
+ String value;
+ VariantWriter::write_to_string(params[base], value);
+ f->store_line(base + "=" + value);
+ }
}
// Store the md5's of the various files. These are stored separately so that the .import files can be version controlled.
- Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
- ERR_FAIL_COND_MSG(md5s.is_null(), "Cannot open MD5 file '" + base_path + ".md5'.");
+ {
+ Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
+ ERR_FAIL_COND_MSG(md5s.is_null(), "Cannot open MD5 file '" + base_path + ".md5'.");
- md5s->store_line("source_md5=\"" + FileAccess::get_md5(p_file) + "\"");
- if (dest_paths.size()) {
- md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+ md5s->store_line("source_md5=\"" + FileAccess::get_md5(p_file) + "\"");
+ if (dest_paths.size()) {
+ md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+ }
}
//update modified times, to avoid reimport
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index aa10d7e68e..8541918e88 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -263,28 +263,31 @@ void EditorResourcePreview::_iterate() {
if (tsize != thumbnail_size) {
cache_valid = false;
+ f.unref();
} else if (last_modtime != modtime) {
String last_md5 = f->get_line();
String md5 = FileAccess::get_md5(item.path);
+ f.unref();
if (last_md5 != md5) {
cache_valid = false;
-
} else {
//update modified time
- f = FileAccess::open(file, FileAccess::WRITE);
- if (f.is_null()) {
+ Ref<FileAccess> f2 = FileAccess::open(file, FileAccess::WRITE);
+ if (f2.is_null()) {
// Not returning as this would leave the thread hanging and would require
// some proper cleanup/disabling of resource preview generation.
ERR_PRINT("Cannot create file '" + file + "'. Check user write permissions.");
} else {
- f->store_line(itos(thumbnail_size));
- f->store_line(itos(has_small_texture));
- f->store_line(itos(modtime));
- f->store_line(md5);
+ f2->store_line(itos(thumbnail_size));
+ f2->store_line(itos(has_small_texture));
+ f2->store_line(itos(modtime));
+ f2->store_line(md5);
}
}
+ } else {
+ f.unref();
}
if (cache_valid) {
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index a1fd2d9049..06c179e77c 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -514,7 +514,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
}
f->store_buffer(data.ptr(), data.size());
-
+ f.unref(); // close file.
#ifndef WINDOWS_ENABLED
FileAccess::set_unix_permissions(to_write, (info.external_fa >> 16) & 0x01FF);
#endif
@@ -728,6 +728,7 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
Ref<FileAccess> f = FileAccess::open(to_write, FileAccess::WRITE);
if (f.is_valid()) {
f->store_buffer(data.ptr(), data.size());
+ f.unref(); // close file.
#ifndef WINDOWS_ENABLED
FileAccess::set_unix_permissions(to_write, (info.external_fa >> 16) & 0x01FF);
#endif
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 2081edca25..17a1bd1048 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -783,6 +783,7 @@ void AnimationPlayerEditor::_update_player() {
ITEM_CHECK_DISABLED(TOOL_RENAME_ANIM);
ITEM_CHECK_DISABLED(TOOL_EDIT_TRANSITIONS);
ITEM_CHECK_DISABLED(TOOL_REMOVE_ANIM);
+ ITEM_CHECK_DISABLED(TOOL_EDIT_RESOURCE);
#undef ITEM_CHECK_DISABLED
@@ -1079,15 +1080,9 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
_animation_remove();
} break;
case TOOL_EDIT_RESOURCE: {
- if (!animation->has_selectable_items()) {
- error_dialog->set_text(TTR("No animation to edit!"));
- error_dialog->popup_centered();
- return;
+ if (anim.is_valid()) {
+ EditorNode::get_singleton()->edit_resource(anim);
}
-
- String current2 = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim2 = player->get_animation(current2);
- EditorNode::get_singleton()->edit_resource(anim2);
} break;
}
}
diff --git a/editor/plugins/ot_features_plugin.cpp b/editor/plugins/ot_features_plugin.cpp
index 27b35d803c..936eb747b0 100644
--- a/editor/plugins/ot_features_plugin.cpp
+++ b/editor/plugins/ot_features_plugin.cpp
@@ -145,8 +145,11 @@ void OpenTypeFeaturesAdd::setup(Object *p_object) {
void OpenTypeFeaturesAdd::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_ENTER_TREE: {
+ connect("pressed", callable_mp(this, &OpenTypeFeaturesAdd::_features_menu));
+ [[fallthrough]];
+ }
+ case NOTIFICATION_THEME_CHANGED: {
set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
} break;
}
@@ -173,7 +176,6 @@ OpenTypeFeaturesAdd::OpenTypeFeaturesAdd() {
menu_cu->set_name("CUMenu");
menu->add_child(menu_cu);
- connect("pressed", callable_mp(this, &OpenTypeFeaturesAdd::_features_menu));
menu->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
menu_cv->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
menu_ss->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 09bff7c00b..906edb006c 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1091,10 +1091,12 @@ void ScriptEditor::_file_dialog_action(String p_file) {
switch (file_dialog_option) {
case FILE_NEW_TEXTFILE: {
Error err;
- Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
- if (err) {
- EditorNode::get_singleton()->show_warning(TTR("Error writing TextFile:") + "\n" + p_file, TTR("Error!"));
- break;
+ {
+ Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+ if (err) {
+ EditorNode::get_singleton()->show_warning(TTR("Error writing TextFile:") + "\n" + p_file, TTR("Error!"));
+ break;
+ }
}
if (EditorFileSystem::get_singleton()) {
@@ -2209,13 +2211,15 @@ Error ScriptEditor::_save_text_file(Ref<TextFile> p_text_file, const String &p_p
String source = sqscr->get_text();
Error err;
- Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ {
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V_MSG(err, err, "Cannot save text file '" + p_path + "'.");
+ ERR_FAIL_COND_V_MSG(err, err, "Cannot save text file '" + p_path + "'.");
- file->store_string(source);
- if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
- return ERR_CANT_CREATE;
+ file->store_string(source);
+ if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+ return ERR_CANT_CREATE;
+ }
}
if (ResourceSaver::get_timestamp_on_save()) {
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 87b5b829e0..27160f8c86 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -43,6 +43,11 @@
#include "scene/gui/margin_container.h"
#include "scene/gui/panel_container.h"
+static void _draw_shadowed_line(Control *p_control, const Point2 &p_from, const Size2 &p_size, const Size2 &p_shadow_offset, Color p_color, Color p_shadow_color) {
+ p_control->draw_line(p_from, p_from + p_size, p_color);
+ p_control->draw_line(p_from + p_shadow_offset, p_from + p_size + p_shadow_offset, p_shadow_color);
+}
+
void SpriteFramesEditor::gui_input(const Ref<InputEvent> &p_event) {
}
@@ -58,46 +63,62 @@ void SpriteFramesEditor::_open_sprite_sheet() {
}
int SpriteFramesEditor::_sheet_preview_position_to_frame_index(const Point2 &p_position) {
- if (p_position.x < 0 || p_position.y < 0) {
- return -1;
- }
+ const Size2i offset = _get_offset();
+ const Size2i frame_size = _get_frame_size();
+ const Size2i separation = _get_separation();
+ const Size2i block_size = frame_size + separation;
+ const Point2i position = p_position / sheet_zoom - offset;
- Size2i texture_size = split_sheet_preview->get_texture()->get_size();
- int h = split_sheet_h->get_value();
- int v = split_sheet_v->get_value();
- if (h > texture_size.width || v > texture_size.height) {
- return -1;
+ if (position.x % block_size.x > frame_size.x || position.y % block_size.y > frame_size.y) {
+ return -1; // Gap between frames.
}
- int x = int(p_position.x / sheet_zoom) / (texture_size.width / h);
- int y = int(p_position.y / sheet_zoom) / (texture_size.height / v);
- if (x >= h || y >= v) {
- return -1;
+ const Point2i frame = position / block_size;
+ const Size2i frame_count = _get_frame_count();
+ if (frame.x < 0 || frame.y < 0 || frame.x >= frame_count.x || frame.y >= frame_count.y) {
+ return -1; // Out of bound.
}
- return h * y + x;
+
+ return frame_count.x * frame.y + frame.x;
}
void SpriteFramesEditor::_sheet_preview_draw() {
- Size2i texture_size = split_sheet_preview->get_texture()->get_size();
- int h = split_sheet_h->get_value();
- int v = split_sheet_v->get_value();
-
- real_t width = (texture_size.width / h) * sheet_zoom;
- real_t height = (texture_size.height / v) * sheet_zoom;
- const float a = 0.3;
-
- real_t y_end = v * height;
- for (int i = 0; i <= h; i++) {
- real_t x = i * width;
- split_sheet_preview->draw_line(Point2(x, 0), Point2(x, y_end), Color(1, 1, 1, a));
- split_sheet_preview->draw_line(Point2(x + 1, 0), Point2(x + 1, y_end), Color(0, 0, 0, a));
+ const Size2i frame_count = _get_frame_count();
+ const Size2i separation = _get_separation();
+
+ const Size2 draw_offset = Size2(_get_offset()) * sheet_zoom;
+ const Size2 draw_sep = Size2(separation) * sheet_zoom;
+ const Size2 draw_frame_size = Size2(_get_frame_size()) * sheet_zoom;
+ const Size2 draw_size = draw_frame_size * frame_count + draw_sep * (frame_count - Size2i(1, 1));
+
+ const Color line_color = Color(1, 1, 1, 0.3);
+ const Color shadow_color = Color(0, 0, 0, 0.3);
+
+ // Vertical lines.
+ _draw_shadowed_line(split_sheet_preview, draw_offset, Vector2(0, draw_size.y), Vector2(1, 0), line_color, shadow_color);
+ for (int i = 0; i < frame_count.x - 1; i++) {
+ const Point2 start = draw_offset + Vector2(i * draw_sep.x + (i + 1) * draw_frame_size.x, 0);
+ if (separation.x == 0) {
+ _draw_shadowed_line(split_sheet_preview, start, Vector2(0, draw_size.y), Vector2(1, 0), line_color, shadow_color);
+ } else {
+ const Size2 size = Size2(draw_sep.x, draw_size.y);
+ split_sheet_preview->draw_rect(Rect2(start, size), line_color);
+ }
}
- real_t x_end = h * width;
- for (int i = 0; i <= v; i++) {
- real_t y = i * height;
- split_sheet_preview->draw_line(Point2(0, y), Point2(x_end, y), Color(1, 1, 1, a));
- split_sheet_preview->draw_line(Point2(0, y + 1), Point2(x_end, y + 1), Color(0, 0, 0, a));
+ _draw_shadowed_line(split_sheet_preview, draw_offset + Vector2(draw_size.x, 0), Vector2(0, draw_size.y), Vector2(1, 0), line_color, shadow_color);
+
+ // Horizontal lines.
+ _draw_shadowed_line(split_sheet_preview, draw_offset, Vector2(draw_size.x, 0), Vector2(0, 1), line_color, shadow_color);
+ for (int i = 0; i < frame_count.y - 1; i++) {
+ const Point2 start = draw_offset + Vector2(0, i * draw_sep.y + (i + 1) * draw_frame_size.y);
+ if (separation.y == 0) {
+ _draw_shadowed_line(split_sheet_preview, start, Vector2(draw_size.x, 0), Vector2(0, 1), line_color, shadow_color);
+ } else {
+ const Size2 size = Size2(draw_size.x, draw_sep.y);
+ split_sheet_preview->draw_rect(Rect2(start, size), line_color);
+ }
}
+ _draw_shadowed_line(split_sheet_preview, draw_offset + Vector2(0, draw_size.y), Vector2(draw_size.x, 0), Vector2(0, 1), line_color, shadow_color);
if (frames_selected.size() == 0) {
split_sheet_dialog->get_ok_button()->set_disabled(true);
@@ -105,22 +126,20 @@ void SpriteFramesEditor::_sheet_preview_draw() {
return;
}
- Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ Color accent = get_theme_color("accent_color", "Editor");
for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) {
- int idx = E->get();
- int xp = idx % h;
- int yp = idx / h;
- real_t x = xp * width;
- real_t y = yp * height;
-
- split_sheet_preview->draw_rect(Rect2(x + 5, y + 5, width - 10, height - 10), Color(0, 0, 0, 0.35), true);
- split_sheet_preview->draw_rect(Rect2(x + 0, y + 0, width - 0, height - 0), Color(0, 0, 0, 1), false);
- split_sheet_preview->draw_rect(Rect2(x + 1, y + 1, width - 2, height - 2), Color(0, 0, 0, 1), false);
- split_sheet_preview->draw_rect(Rect2(x + 2, y + 2, width - 4, height - 4), accent, false);
- split_sheet_preview->draw_rect(Rect2(x + 3, y + 3, width - 6, height - 6), accent, false);
- split_sheet_preview->draw_rect(Rect2(x + 4, y + 4, width - 8, height - 8), Color(0, 0, 0, 1), false);
- split_sheet_preview->draw_rect(Rect2(x + 5, y + 5, width - 10, height - 10), Color(0, 0, 0, 1), false);
+ const int idx = E->get();
+ const int x = idx % frame_count.x;
+ const int y = idx / frame_count.x;
+ const Point2 pos = draw_offset + Point2(x, y) * (draw_frame_size + draw_sep);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(5, 5), draw_frame_size - Size2(10, 10)), Color(0, 0, 0, 0.35), true);
+ split_sheet_preview->draw_rect(Rect2(pos, draw_frame_size), Color(0, 0, 0, 1), false);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(1, 1), draw_frame_size - Size2(2, 2)), Color(0, 0, 0, 1), false);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(2, 2), draw_frame_size - Size2(4, 4)), accent, false);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(3, 3), draw_frame_size - Size2(6, 6)), accent, false);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(4, 4), draw_frame_size - Size2(8, 8)), Color(0, 0, 0, 1), false);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(5, 5), draw_frame_size - Size2(10, 10)), Color(0, 0, 0, 1), false);
}
split_sheet_dialog->get_ok_button()->set_disabled(false);
@@ -223,10 +242,10 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) {
}
void SpriteFramesEditor::_sheet_add_frames() {
- Size2i texture_size = split_sheet_preview->get_texture()->get_size();
- int frame_count_x = split_sheet_h->get_value();
- int frame_count_y = split_sheet_v->get_value();
- Size2 frame_size(texture_size.width / frame_count_x, texture_size.height / frame_count_y);
+ const Size2i frame_count = _get_frame_count();
+ const Size2i frame_size = _get_frame_size();
+ const Size2i offset = _get_offset();
+ const Size2i separation = _get_separation();
undo_redo->create_action(TTR("Add Frame"));
@@ -234,12 +253,12 @@ void SpriteFramesEditor::_sheet_add_frames() {
for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) {
int idx = E->get();
- Point2 frame_coords(idx % frame_count_x, idx / frame_count_x);
+ const Point2 frame_coords(idx % frame_count.x, idx / frame_count.x);
Ref<AtlasTexture> at;
at.instantiate();
at->set_atlas(split_sheet_preview->get_texture());
- at->set_region(Rect2(frame_coords * frame_size, frame_size));
+ at->set_region(Rect2(offset + frame_coords * (frame_size + separation), frame_size));
undo_redo->add_do_method(frames, "add_frame", edited_anim, at, -1);
undo_redo->add_undo_method(frames, "remove_frame", edited_anim, fc);
@@ -293,7 +312,57 @@ void SpriteFramesEditor::_sheet_select_clear_all_frames() {
split_sheet_preview->update();
}
-void SpriteFramesEditor::_sheet_spin_changed(double) {
+void SpriteFramesEditor::_sheet_spin_changed(double p_value, int p_dominant_param) {
+ if (updating_split_settings) {
+ return;
+ }
+ updating_split_settings = true;
+
+ if (p_dominant_param != PARAM_USE_CURRENT) {
+ dominant_param = p_dominant_param;
+ }
+
+ const Size2i texture_size = split_sheet_preview->get_texture()->get_size();
+ const Size2i size = texture_size - _get_offset();
+
+ switch (dominant_param) {
+ case PARAM_SIZE: {
+ const Size2i frame_size = _get_frame_size();
+
+ const Size2i offset_max = texture_size - frame_size;
+ split_sheet_offset_x->set_max(offset_max.x);
+ split_sheet_offset_y->set_max(offset_max.y);
+
+ const Size2i sep_max = size - frame_size * 2;
+ split_sheet_sep_x->set_max(sep_max.x);
+ split_sheet_sep_y->set_max(sep_max.y);
+
+ const Size2i separation = _get_separation();
+ const Size2i count = (size + separation) / (frame_size + separation);
+ split_sheet_h->set_value(count.x);
+ split_sheet_v->set_value(count.y);
+ } break;
+
+ case PARAM_FRAME_COUNT: {
+ const Size2i count = _get_frame_count();
+
+ const Size2i offset_max = texture_size - count;
+ split_sheet_offset_x->set_max(offset_max.x);
+ split_sheet_offset_y->set_max(offset_max.y);
+
+ const Size2i gap_count = count - Size2i(1, 1);
+ split_sheet_sep_x->set_max(gap_count.x == 0 ? size.x : (size.x - count.x) / gap_count.x);
+ split_sheet_sep_y->set_max(gap_count.y == 0 ? size.y : (size.y - count.y) / gap_count.y);
+
+ const Size2i separation = _get_separation();
+ const Size2i frame_size = (size - separation * gap_count) / count;
+ split_sheet_size_x->set_value(frame_size.x);
+ split_sheet_size_y->set_value(frame_size.y);
+ } break;
+ }
+
+ updating_split_settings = false;
+
frames_selected.clear();
last_frame_selected = -1;
split_sheet_preview->update();
@@ -311,10 +380,29 @@ void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
bool new_texture = texture != split_sheet_preview->get_texture();
split_sheet_preview->set_texture(texture);
if (new_texture) {
- //different texture, reset to 4x4
+ // Reset spin max.
+ const Size2i size = texture->get_size();
+ split_sheet_size_x->set_max(size.x);
+ split_sheet_size_y->set_max(size.y);
+ split_sheet_sep_x->set_max(size.x);
+ split_sheet_sep_y->set_max(size.y);
+ split_sheet_offset_x->set_max(size.x);
+ split_sheet_offset_y->set_max(size.y);
+
+ // Different texture, reset to 4x4.
+ dominant_param = PARAM_FRAME_COUNT;
+ updating_split_settings = true;
split_sheet_h->set_value(4);
split_sheet_v->set_value(4);
- //reset zoom
+ split_sheet_size_x->set_value(size.x / 4);
+ split_sheet_size_y->set_value(size.y / 4);
+ split_sheet_sep_x->set_value(0);
+ split_sheet_sep_y->set_value(0);
+ split_sheet_offset_x->set_value(0);
+ split_sheet_offset_y->set_value(0);
+ updating_split_settings = false;
+
+ // Reset zoom.
_sheet_zoom_reset();
}
split_sheet_dialog->popup_centered_ratio(0.65);
@@ -392,6 +480,22 @@ void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_
undo_redo->commit_action();
}
+Size2i SpriteFramesEditor::_get_frame_count() const {
+ return Size2i(split_sheet_h->get_value(), split_sheet_v->get_value());
+}
+
+Size2i SpriteFramesEditor::_get_frame_size() const {
+ return Size2i(split_sheet_size_x->get_value(), split_sheet_size_y->get_value());
+}
+
+Size2i SpriteFramesEditor::_get_offset() const {
+ return Size2i(split_sheet_offset_x->get_value(), split_sheet_offset_y->get_value());
+}
+
+Size2i SpriteFramesEditor::_get_separation() const {
+ return Size2i(split_sheet_sep_x->get_value(), split_sheet_sep_y->get_value());
+}
+
void SpriteFramesEditor::_load_pressed() {
ERR_FAIL_COND(!frames->has_animation(edited_anim));
loading_scene = false;
@@ -1210,23 +1314,66 @@ SpriteFramesEditor::SpriteFramesEditor() {
HBoxContainer *split_sheet_hb = memnew(HBoxContainer);
- Label *ss_label = memnew(Label(TTR("Horizontal:")));
- split_sheet_hb->add_child(ss_label);
+ split_sheet_hb->add_child(memnew(Label(TTR("Horizontal:"))));
split_sheet_h = memnew(SpinBox);
split_sheet_h->set_min(1);
split_sheet_h->set_max(128);
split_sheet_h->set_step(1);
split_sheet_hb->add_child(split_sheet_h);
- split_sheet_h->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed));
+ split_sheet_h->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_FRAME_COUNT));
- ss_label = memnew(Label(TTR("Vertical:")));
- split_sheet_hb->add_child(ss_label);
+ split_sheet_hb->add_child(memnew(Label(TTR("Vertical:"))));
split_sheet_v = memnew(SpinBox);
split_sheet_v->set_min(1);
split_sheet_v->set_max(128);
split_sheet_v->set_step(1);
split_sheet_hb->add_child(split_sheet_v);
- split_sheet_v->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed));
+ split_sheet_v->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_FRAME_COUNT));
+
+ split_sheet_hb->add_child(memnew(VSeparator));
+ split_sheet_hb->add_child(memnew(Label(TTR("Size:"))));
+ split_sheet_size_x = memnew(SpinBox);
+ split_sheet_size_x->set_min(1);
+ split_sheet_size_x->set_step(1);
+ split_sheet_size_x->set_suffix("px");
+ split_sheet_size_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_SIZE));
+ split_sheet_hb->add_child(split_sheet_size_x);
+ split_sheet_size_y = memnew(SpinBox);
+ split_sheet_size_y->set_min(1);
+ split_sheet_size_y->set_step(1);
+ split_sheet_size_y->set_suffix("px");
+ split_sheet_size_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_SIZE));
+ split_sheet_hb->add_child(split_sheet_size_y);
+
+ split_sheet_hb->add_child(memnew(VSeparator));
+ split_sheet_hb->add_child(memnew(Label(TTR("Separation:"))));
+ split_sheet_sep_x = memnew(SpinBox);
+ split_sheet_sep_x->set_min(0);
+ split_sheet_sep_x->set_step(1);
+ split_sheet_sep_x->set_suffix("px");
+ split_sheet_sep_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_hb->add_child(split_sheet_sep_x);
+ split_sheet_sep_y = memnew(SpinBox);
+ split_sheet_sep_y->set_min(0);
+ split_sheet_sep_y->set_step(1);
+ split_sheet_sep_y->set_suffix("px");
+ split_sheet_sep_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_hb->add_child(split_sheet_sep_y);
+
+ split_sheet_hb->add_child(memnew(VSeparator));
+ split_sheet_hb->add_child(memnew(Label(TTR("Offset:"))));
+ split_sheet_offset_x = memnew(SpinBox);
+ split_sheet_offset_x->set_min(0);
+ split_sheet_offset_x->set_step(1);
+ split_sheet_offset_x->set_suffix("px");
+ split_sheet_offset_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_hb->add_child(split_sheet_offset_x);
+ split_sheet_offset_y = memnew(SpinBox);
+ split_sheet_offset_y->set_min(0);
+ split_sheet_offset_y->set_step(1);
+ split_sheet_offset_y->set_suffix("px");
+ split_sheet_offset_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_hb->add_child(split_sheet_offset_y);
split_sheet_hb->add_spacer();
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index b0213012a2..9a00fe5771 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -48,6 +48,13 @@ class EditorFileDialog;
class SpriteFramesEditor : public HSplitContainer {
GDCLASS(SpriteFramesEditor, HSplitContainer);
+ enum {
+ PARAM_USE_CURRENT, // Used in callbacks to indicate `dominant_param` should be not updated.
+ PARAM_FRAME_COUNT, // Keep "Horizontal" & "Vertial" values.
+ PARAM_SIZE, // Keep "Size" values.
+ };
+ int dominant_param = PARAM_FRAME_COUNT;
+
Button *load = nullptr;
Button *load_sheet = nullptr;
Button *_delete = nullptr;
@@ -86,6 +93,12 @@ class SpriteFramesEditor : public HSplitContainer {
TextureRect *split_sheet_preview = nullptr;
SpinBox *split_sheet_h = nullptr;
SpinBox *split_sheet_v = nullptr;
+ SpinBox *split_sheet_size_x = nullptr;
+ SpinBox *split_sheet_size_y = nullptr;
+ SpinBox *split_sheet_sep_x = nullptr;
+ SpinBox *split_sheet_sep_y = nullptr;
+ SpinBox *split_sheet_offset_x = nullptr;
+ SpinBox *split_sheet_offset_y = nullptr;
Button *split_sheet_zoom_out = nullptr;
Button *split_sheet_zoom_reset = nullptr;
Button *split_sheet_zoom_in = nullptr;
@@ -103,6 +116,11 @@ class SpriteFramesEditor : public HSplitContainer {
float max_sheet_zoom;
float min_sheet_zoom;
+ Size2i _get_frame_count() const;
+ Size2i _get_frame_size() const;
+ Size2i _get_offset() const;
+ Size2i _get_separation() const;
+
void _load_pressed();
void _file_load_request(const Vector<String> &p_path, int p_at_pos = -1);
void _copy_pressed();
@@ -128,6 +146,7 @@ class SpriteFramesEditor : public HSplitContainer {
void _zoom_reset();
bool updating;
+ bool updating_split_settings = false; // Skip SpinBox/Range callback when setting value by code.
UndoRedo *undo_redo = nullptr;
@@ -139,7 +158,7 @@ class SpriteFramesEditor : public HSplitContainer {
void _prepare_sprite_sheet(const String &p_file);
int _sheet_preview_position_to_frame_index(const Vector2 &p_position);
void _sheet_preview_draw();
- void _sheet_spin_changed(double);
+ void _sheet_spin_changed(double p_value, int p_dominant_param);
void _sheet_preview_input(const Ref<InputEvent> &p_event);
void _sheet_scroll_input(const Ref<InputEvent> &p_event);
void _sheet_add_frames();
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index a7c06ada5c..15f03fd46d 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -70,7 +70,7 @@ void TexturePreview::_update_metadata_label_text() {
format = texture->get_class();
}
- metadata_label->set_text(itos(texture->get_width()) + "x" + itos(texture->get_height()) + " " + format);
+ metadata_label->set_text(vformat(String::utf8("%s×%s %s"), itos(texture->get_width()), itos(texture->get_height()), format));
}
TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {