Merge pull request #58751 from bruvzg/loc_str_props
This commit is contained in:
commit
952b71a425
14 changed files with 423 additions and 43 deletions
|
@ -1199,6 +1199,8 @@ ProjectSettings::ProjectSettings() {
|
||||||
singleton = this;
|
singleton = this;
|
||||||
|
|
||||||
GLOBAL_DEF_BASIC("application/config/name", "");
|
GLOBAL_DEF_BASIC("application/config/name", "");
|
||||||
|
GLOBAL_DEF_BASIC("application/config/name_localized", Dictionary());
|
||||||
|
custom_prop_info["application/config/name_localized"] = PropertyInfo(Variant::DICTIONARY, "application/config/name_localized", PROPERTY_HINT_LOCALIZABLE_STRING);
|
||||||
GLOBAL_DEF_BASIC("application/config/description", "");
|
GLOBAL_DEF_BASIC("application/config/description", "");
|
||||||
custom_prop_info["application/config/description"] = PropertyInfo(Variant::STRING, "application/config/description", PROPERTY_HINT_MULTILINE_TEXT);
|
custom_prop_info["application/config/description"] = PropertyInfo(Variant::STRING, "application/config/description", PROPERTY_HINT_MULTILINE_TEXT);
|
||||||
GLOBAL_DEF_BASIC("application/run/main_scene", "");
|
GLOBAL_DEF_BASIC("application/run/main_scene", "");
|
||||||
|
|
|
@ -591,6 +591,7 @@ void register_global_constants() {
|
||||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_POINTER);
|
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_POINTER);
|
||||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE);
|
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE);
|
||||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALE_ID);
|
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALE_ID);
|
||||||
|
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALIZABLE_STRING);
|
||||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
|
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
|
||||||
|
|
||||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE);
|
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE);
|
||||||
|
|
|
@ -88,6 +88,7 @@ enum PropertyHint {
|
||||||
PROPERTY_HINT_ARRAY_TYPE,
|
PROPERTY_HINT_ARRAY_TYPE,
|
||||||
PROPERTY_HINT_INT_IS_POINTER,
|
PROPERTY_HINT_INT_IS_POINTER,
|
||||||
PROPERTY_HINT_LOCALE_ID,
|
PROPERTY_HINT_LOCALE_ID,
|
||||||
|
PROPERTY_HINT_LOCALIZABLE_STRING,
|
||||||
PROPERTY_HINT_MAX,
|
PROPERTY_HINT_MAX,
|
||||||
// When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit
|
// When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit
|
||||||
};
|
};
|
||||||
|
|
|
@ -2516,7 +2516,10 @@
|
||||||
<constant name="PROPERTY_HINT_LOCALE_ID" value="41" enum="PropertyHint">
|
<constant name="PROPERTY_HINT_LOCALE_ID" value="41" enum="PropertyHint">
|
||||||
Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country.
|
Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="PROPERTY_HINT_MAX" value="42" enum="PropertyHint">
|
<constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="42" enum="PropertyHint">
|
||||||
|
Hints that a dictionary property is string translation map. Dictionary keys are locale codes and, values are translated strings.
|
||||||
|
</constant>
|
||||||
|
<constant name="PROPERTY_HINT_MAX" value="43" enum="PropertyHint">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags">
|
<constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags">
|
||||||
</constant>
|
</constant>
|
||||||
|
|
|
@ -226,6 +226,9 @@
|
||||||
The project's name. It is used both by the Project Manager and by exporters. The project name can be translated by translating its value in localization files. The window title will be set to match the project name automatically on startup.
|
The project's name. It is used both by the Project Manager and by exporters. The project name can be translated by translating its value in localization files. The window title will be set to match the project name automatically on startup.
|
||||||
[b]Note:[/b] Changing this value will also change the user data folder's path if [member application/config/use_custom_user_dir] is [code]false[/code]. After renaming the project, you will no longer be able to access existing data in [code]user://[/code] unless you rename the old folder to match the new project name. See [url=$DOCS_URL/tutorials/io/data_paths.html]Data paths[/url] in the documentation for more information.
|
[b]Note:[/b] Changing this value will also change the user data folder's path if [member application/config/use_custom_user_dir] is [code]false[/code]. After renaming the project, you will no longer be able to access existing data in [code]user://[/code] unless you rename the old folder to match the new project name. See [url=$DOCS_URL/tutorials/io/data_paths.html]Data paths[/url] in the documentation for more information.
|
||||||
</member>
|
</member>
|
||||||
|
<member name="application/config/name_localized" type="Dictionary" setter="" getter="" default="{}">
|
||||||
|
Translations of the project's name. This setting is used by OS tools to translate application name on Android, iOS and macOS.
|
||||||
|
</member>
|
||||||
<member name="application/config/project_settings_override" type="String" setter="" getter="" default="""">
|
<member name="application/config/project_settings_override" type="String" setter="" getter="" default="""">
|
||||||
Specifies a file to override project settings. For example: [code]user://custom_settings.cfg[/code]. See "Overriding" in the [ProjectSettings] class description at the top for more information.
|
Specifies a file to override project settings. For example: [code]user://custom_settings.cfg[/code]. See "Overriding" in the [ProjectSettings] class description at the top for more information.
|
||||||
[b]Note:[/b] Regardless of this setting's value, [code]res://override.cfg[/code] will still be read to override the project settings.
|
[b]Note:[/b] Regardless of this setting's value, [code]res://override.cfg[/code] will still be read to override the project settings.
|
||||||
|
|
|
@ -3738,8 +3738,13 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Variant::DICTIONARY: {
|
case Variant::DICTIONARY: {
|
||||||
|
if (p_hint == PROPERTY_HINT_LOCALIZABLE_STRING) {
|
||||||
|
EditorPropertyLocalizableString *editor = memnew(EditorPropertyLocalizableString);
|
||||||
|
return editor;
|
||||||
|
} else {
|
||||||
EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary);
|
EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary);
|
||||||
return editor;
|
return editor;
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case Variant::ARRAY: {
|
case Variant::ARRAY: {
|
||||||
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
||||||
|
|
|
@ -742,7 +742,7 @@ void EditorPropertyDictionary::_property_changed(const String &p_property, Varia
|
||||||
|
|
||||||
emit_changed(get_edited_property(), dict, "", true);
|
emit_changed(get_edited_property(), dict, "", true);
|
||||||
|
|
||||||
dict = dict.duplicate(); // Duplicate, so undo/redo works better\.
|
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
|
||||||
object->set_dict(dict);
|
object->set_dict(dict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -805,7 +805,7 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) {
|
||||||
|
|
||||||
emit_changed(get_edited_property(), dict, "", false);
|
emit_changed(get_edited_property(), dict, "", false);
|
||||||
|
|
||||||
dict = dict.duplicate(); // Duplicate, so undo/redo works better\.
|
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
|
||||||
object->set_dict(dict);
|
object->set_dict(dict);
|
||||||
update_property();
|
update_property();
|
||||||
}
|
}
|
||||||
|
@ -814,7 +814,7 @@ void EditorPropertyDictionary::update_property() {
|
||||||
Variant updated_val = get_edited_object()->get(get_edited_property());
|
Variant updated_val = get_edited_object()->get(get_edited_property());
|
||||||
|
|
||||||
if (updated_val.get_type() == Variant::NIL) {
|
if (updated_val.get_type() == Variant::NIL) {
|
||||||
edit->set_text("Dictionary (Nil)"); // This provides symmetry with the array property.
|
edit->set_text(TTR("Dictionary (Nil)")); // This provides symmetry with the array property.
|
||||||
edit->set_pressed(false);
|
edit->set_pressed(false);
|
||||||
if (vbox) {
|
if (vbox) {
|
||||||
set_bottom_editor(nullptr);
|
set_bottom_editor(nullptr);
|
||||||
|
@ -826,7 +826,7 @@ void EditorPropertyDictionary::update_property() {
|
||||||
|
|
||||||
Dictionary dict = updated_val;
|
Dictionary dict = updated_val;
|
||||||
|
|
||||||
edit->set_text("Dictionary (size " + itos(dict.size()) + ")");
|
edit->set_text(vformat(TTR("Dictionary (size %d)"), dict.size()));
|
||||||
|
|
||||||
bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
|
bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
|
||||||
if (edit->is_pressed() != unfolded) {
|
if (edit->is_pressed() != unfolded) {
|
||||||
|
@ -1144,6 +1144,7 @@ void EditorPropertyDictionary::update_property() {
|
||||||
if (vbox) {
|
if (vbox) {
|
||||||
set_bottom_editor(nullptr);
|
set_bottom_editor(nullptr);
|
||||||
memdelete(vbox);
|
memdelete(vbox);
|
||||||
|
button_add_item = nullptr;
|
||||||
vbox = nullptr;
|
vbox = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1216,3 +1217,226 @@ EditorPropertyDictionary::EditorPropertyDictionary() {
|
||||||
change_type->connect("id_pressed", callable_mp(this, &EditorPropertyDictionary::_change_type_menu));
|
change_type->connect("id_pressed", callable_mp(this, &EditorPropertyDictionary::_change_type_menu));
|
||||||
changing_type_index = -1;
|
changing_type_index = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////// LOCALIZABLE STRING ///////////////////////////
|
||||||
|
|
||||||
|
void EditorPropertyLocalizableString::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
|
||||||
|
if (p_property.begins_with("indices")) {
|
||||||
|
int index = p_property.get_slice("/", 1).to_int();
|
||||||
|
Dictionary dict = object->get_dict();
|
||||||
|
Variant key = dict.get_key_at_index(index);
|
||||||
|
dict[key] = p_value;
|
||||||
|
|
||||||
|
emit_changed(get_edited_property(), dict, "", true);
|
||||||
|
|
||||||
|
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
|
||||||
|
object->set_dict(dict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyLocalizableString::_add_locale_popup() {
|
||||||
|
locale_select->popup_locale_dialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyLocalizableString::_add_locale(const String &p_locale) {
|
||||||
|
Dictionary dict = object->get_dict();
|
||||||
|
|
||||||
|
object->set_new_item_key(p_locale);
|
||||||
|
object->set_new_item_value(String());
|
||||||
|
dict[object->get_new_item_key()] = object->get_new_item_value();
|
||||||
|
|
||||||
|
emit_changed(get_edited_property(), dict, "", false);
|
||||||
|
|
||||||
|
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
|
||||||
|
object->set_dict(dict);
|
||||||
|
update_property();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyLocalizableString::_remove_item(Object *p_button, int p_index) {
|
||||||
|
Dictionary dict = object->get_dict();
|
||||||
|
|
||||||
|
Variant key = dict.get_key_at_index(p_index);
|
||||||
|
dict.erase(key);
|
||||||
|
|
||||||
|
emit_changed(get_edited_property(), dict, "", false);
|
||||||
|
|
||||||
|
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
|
||||||
|
object->set_dict(dict);
|
||||||
|
update_property();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyLocalizableString::update_property() {
|
||||||
|
Variant updated_val = get_edited_object()->get(get_edited_property());
|
||||||
|
|
||||||
|
if (updated_val.get_type() == Variant::NIL) {
|
||||||
|
edit->set_text(TTR("Localizable String (Nil)")); // This provides symmetry with the array property.
|
||||||
|
edit->set_pressed(false);
|
||||||
|
if (vbox) {
|
||||||
|
set_bottom_editor(nullptr);
|
||||||
|
memdelete(vbox);
|
||||||
|
vbox = nullptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary dict = updated_val;
|
||||||
|
|
||||||
|
edit->set_text(vformat(TTR("Localizable String (size %d)"), dict.size()));
|
||||||
|
|
||||||
|
bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
|
||||||
|
if (edit->is_pressed() != unfolded) {
|
||||||
|
edit->set_pressed(unfolded);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unfolded) {
|
||||||
|
updating = true;
|
||||||
|
|
||||||
|
if (!vbox) {
|
||||||
|
vbox = memnew(VBoxContainer);
|
||||||
|
add_child(vbox);
|
||||||
|
set_bottom_editor(vbox);
|
||||||
|
|
||||||
|
property_vbox = memnew(VBoxContainer);
|
||||||
|
property_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
vbox->add_child(property_vbox);
|
||||||
|
|
||||||
|
paginator = memnew(EditorPaginator);
|
||||||
|
paginator->connect("page_changed", callable_mp(this, &EditorPropertyLocalizableString::_page_changed));
|
||||||
|
vbox->add_child(paginator);
|
||||||
|
} else {
|
||||||
|
// Queue children for deletion, deleting immediately might cause errors.
|
||||||
|
for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) {
|
||||||
|
property_vbox->get_child(i)->queue_delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = dict.size();
|
||||||
|
|
||||||
|
int max_page = MAX(0, size - 1) / page_length;
|
||||||
|
page_index = MIN(page_index, max_page);
|
||||||
|
|
||||||
|
paginator->update(page_index, max_page);
|
||||||
|
paginator->set_visible(max_page > 0);
|
||||||
|
|
||||||
|
int offset = page_index * page_length;
|
||||||
|
|
||||||
|
int amount = MIN(size - offset, page_length);
|
||||||
|
|
||||||
|
dict = dict.duplicate();
|
||||||
|
|
||||||
|
object->set_dict(dict);
|
||||||
|
|
||||||
|
for (int i = 0; i < amount; i++) {
|
||||||
|
String prop_name;
|
||||||
|
Variant key;
|
||||||
|
Variant value;
|
||||||
|
|
||||||
|
prop_name = "indices/" + itos(i + offset);
|
||||||
|
key = dict.get_key_at_index(i + offset);
|
||||||
|
value = dict.get_value_at_index(i + offset);
|
||||||
|
|
||||||
|
EditorProperty *prop = memnew(EditorPropertyText);
|
||||||
|
|
||||||
|
prop->set_object_and_property(object.ptr(), prop_name);
|
||||||
|
int remove_index = 0;
|
||||||
|
|
||||||
|
String cs = key.get_construct_string();
|
||||||
|
prop->set_label(cs);
|
||||||
|
prop->set_tooltip(cs);
|
||||||
|
remove_index = i + offset;
|
||||||
|
|
||||||
|
prop->set_selectable(false);
|
||||||
|
prop->connect("property_changed", callable_mp(this, &EditorPropertyLocalizableString::_property_changed));
|
||||||
|
prop->connect("object_id_selected", callable_mp(this, &EditorPropertyLocalizableString::_object_id_selected));
|
||||||
|
|
||||||
|
HBoxContainer *hbox = memnew(HBoxContainer);
|
||||||
|
property_vbox->add_child(hbox);
|
||||||
|
hbox->add_child(prop);
|
||||||
|
prop->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
Button *edit = memnew(Button);
|
||||||
|
edit->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
|
||||||
|
hbox->add_child(edit);
|
||||||
|
edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_remove_item), varray(edit, remove_index));
|
||||||
|
|
||||||
|
prop->update_property();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page_index == max_page) {
|
||||||
|
button_add_item = memnew(Button);
|
||||||
|
button_add_item->set_text(TTR("Add Translation"));
|
||||||
|
button_add_item->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
|
||||||
|
button_add_item->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_add_locale_popup));
|
||||||
|
property_vbox->add_child(button_add_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
updating = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (vbox) {
|
||||||
|
set_bottom_editor(nullptr);
|
||||||
|
memdelete(vbox);
|
||||||
|
button_add_item = nullptr;
|
||||||
|
vbox = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyLocalizableString::_object_id_selected(const StringName &p_property, ObjectID p_id) {
|
||||||
|
emit_signal(SNAME("object_id_selected"), p_property, p_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyLocalizableString::_notification(int p_what) {
|
||||||
|
switch (p_what) {
|
||||||
|
case NOTIFICATION_THEME_CHANGED:
|
||||||
|
case NOTIFICATION_ENTER_TREE: {
|
||||||
|
if (Object::cast_to<Button>(button_add_item)) {
|
||||||
|
button_add_item->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyLocalizableString::_edit_pressed() {
|
||||||
|
Variant prop_val = get_edited_object()->get(get_edited_property());
|
||||||
|
if (prop_val.get_type() == Variant::NIL) {
|
||||||
|
Callable::CallError ce;
|
||||||
|
Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
|
||||||
|
get_edited_object()->set(get_edited_property(), prop_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
|
||||||
|
update_property();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyLocalizableString::_page_changed(int p_page) {
|
||||||
|
if (updating) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
page_index = p_page;
|
||||||
|
update_property();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPropertyLocalizableString::_bind_methods() {
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorPropertyLocalizableString::EditorPropertyLocalizableString() {
|
||||||
|
object.instantiate();
|
||||||
|
page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
|
||||||
|
|
||||||
|
edit = memnew(Button);
|
||||||
|
edit->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
edit->set_clip_text(true);
|
||||||
|
edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_edit_pressed));
|
||||||
|
edit->set_toggle_mode(true);
|
||||||
|
add_child(edit);
|
||||||
|
add_focusable(edit);
|
||||||
|
|
||||||
|
vbox = nullptr;
|
||||||
|
button_add_item = nullptr;
|
||||||
|
paginator = nullptr;
|
||||||
|
updating = false;
|
||||||
|
|
||||||
|
locale_select = memnew(EditorLocaleDialog);
|
||||||
|
locale_select->connect("locale_selected", callable_mp(this, &EditorPropertyLocalizableString::_add_locale));
|
||||||
|
add_child(locale_select);
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define EDITOR_PROPERTIES_ARRAY_DICT_H
|
#define EDITOR_PROPERTIES_ARRAY_DICT_H
|
||||||
|
|
||||||
#include "editor/editor_inspector.h"
|
#include "editor/editor_inspector.h"
|
||||||
|
#include "editor/editor_locale_dialog.h"
|
||||||
#include "editor/editor_spin_slider.h"
|
#include "editor/editor_spin_slider.h"
|
||||||
#include "editor/filesystem_dock.h"
|
#include "editor/filesystem_dock.h"
|
||||||
#include "scene/gui/button.h"
|
#include "scene/gui/button.h"
|
||||||
|
@ -169,4 +170,39 @@ public:
|
||||||
EditorPropertyDictionary();
|
EditorPropertyDictionary();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EditorPropertyLocalizableString : public EditorProperty {
|
||||||
|
GDCLASS(EditorPropertyLocalizableString, EditorProperty);
|
||||||
|
|
||||||
|
EditorLocaleDialog *locale_select;
|
||||||
|
|
||||||
|
bool updating;
|
||||||
|
|
||||||
|
Ref<EditorPropertyDictionaryObject> object;
|
||||||
|
int page_length = 20;
|
||||||
|
int page_index = 0;
|
||||||
|
Button *edit;
|
||||||
|
VBoxContainer *vbox;
|
||||||
|
VBoxContainer *property_vbox;
|
||||||
|
EditorSpinSlider *size_slider;
|
||||||
|
Button *button_add_item;
|
||||||
|
EditorPaginator *paginator;
|
||||||
|
|
||||||
|
void _page_changed(int p_page);
|
||||||
|
void _edit_pressed();
|
||||||
|
void _remove_item(Object *p_button, int p_index);
|
||||||
|
void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
|
||||||
|
|
||||||
|
void _add_locale_popup();
|
||||||
|
void _add_locale(const String &p_locale);
|
||||||
|
void _object_id_selected(const StringName &p_property, ObjectID p_id);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
void _notification(int p_what);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void update_property() override;
|
||||||
|
EditorPropertyLocalizableString();
|
||||||
|
};
|
||||||
|
|
||||||
#endif // EDITOR_PROPERTIES_ARRAY_DICT_H
|
#endif // EDITOR_PROPERTIES_ARRAY_DICT_H
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
<string>$name</string>
|
<string>$name</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>$name</string>
|
<string>$name</string>
|
||||||
<key>CFBundleGetInfoString</key>
|
|
||||||
<string>$info</string>
|
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>icon.icns</string>
|
<string>icon.icns</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
|
|
2
misc/dist/osx_tools.app/Contents/Info.plist
vendored
2
misc/dist/osx_tools.app/Contents/Info.plist
vendored
|
@ -8,8 +8,6 @@
|
||||||
<string>Godot</string>
|
<string>Godot</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>Godot</string>
|
<string>Godot</string>
|
||||||
<key>CFBundleGetInfoString</key>
|
|
||||||
<string>(c) 2007-2022 Juan Linietsky, Ariel Manzur & Godot Engine contributors</string>
|
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>Godot.icns</string>
|
<string>Godot.icns</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
|
|
|
@ -1387,6 +1387,7 @@ void EditorExportPlatformAndroid::_fix_resources(const Ref<EditorExportPreset> &
|
||||||
Vector<String> string_table;
|
Vector<String> string_table;
|
||||||
|
|
||||||
String package_name = p_preset->get("package/name");
|
String package_name = p_preset->get("package/name");
|
||||||
|
Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
|
||||||
|
|
||||||
for (uint32_t i = 0; i < string_count; i++) {
|
for (uint32_t i = 0; i < string_count; i++) {
|
||||||
uint32_t offset = decode_uint32(&r_manifest[string_table_begins + i * 4]);
|
uint32_t offset = decode_uint32(&r_manifest[string_table_begins + i * 4]);
|
||||||
|
@ -1401,9 +1402,8 @@ void EditorExportPlatformAndroid::_fix_resources(const Ref<EditorExportPreset> &
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
String lang = str.substr(str.rfind("-") + 1, str.length()).replace("-", "_");
|
String lang = str.substr(str.rfind("-") + 1, str.length()).replace("-", "_");
|
||||||
String prop = "application/config/name_" + lang;
|
if (appnames.has(lang)) {
|
||||||
if (ProjectSettings::get_singleton()->has_setting(prop)) {
|
str = appnames[lang];
|
||||||
str = ProjectSettings::get_singleton()->get(prop);
|
|
||||||
} else {
|
} else {
|
||||||
str = get_project_name(package_name);
|
str = get_project_name(package_name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,7 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset
|
||||||
return ERR_CANT_OPEN;
|
return ERR_CANT_OPEN;
|
||||||
}
|
}
|
||||||
da->list_dir_begin();
|
da->list_dir_begin();
|
||||||
|
Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
|
||||||
while (true) {
|
while (true) {
|
||||||
String file = da->get_next();
|
String file = da->get_next();
|
||||||
if (file.is_empty()) {
|
if (file.is_empty()) {
|
||||||
|
@ -171,10 +172,9 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String locale = file.replace("values-", "").replace("-r", "_");
|
String locale = file.replace("values-", "").replace("-r", "_");
|
||||||
String property_name = "application/config/name_" + locale;
|
|
||||||
String locale_directory = "res://android/build/res/" + file + "/godot_project_name_string.xml";
|
String locale_directory = "res://android/build/res/" + file + "/godot_project_name_string.xml";
|
||||||
if (ProjectSettings::get_singleton()->has_setting(property_name)) {
|
if (appnames.has(locale)) {
|
||||||
String locale_project_name = ProjectSettings::get_singleton()->get(property_name);
|
String locale_project_name = appnames[locale];
|
||||||
String processed_xml_string = vformat(godot_project_name_xml_string, _android_xml_escape(locale_project_name));
|
String processed_xml_string = vformat(godot_project_name_xml_string, _android_xml_escape(locale_project_name));
|
||||||
print_verbose("Storing project name for locale " + locale + " under " + locale_directory);
|
print_verbose("Storing project name for locale " + locale + " under " + locale_directory);
|
||||||
store_string_at_path(locale_directory, processed_xml_string);
|
store_string_at_path(locale_directory, processed_xml_string);
|
||||||
|
|
|
@ -92,13 +92,10 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
|
||||||
|
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/targeted_device_family", PROPERTY_HINT_ENUM, "iPhone,iPad,iPhone & iPad"), 2));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/targeted_device_family", PROPERTY_HINT_ENUM, "iPhone,iPad,iPhone & iPad"), 2));
|
||||||
|
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
|
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
|
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
|
|
||||||
|
|
||||||
Vector<PluginConfigIOS> found_plugins = get_plugins();
|
Vector<PluginConfigIOS> found_plugins = get_plugins();
|
||||||
for (int i = 0; i < found_plugins.size(); i++) {
|
for (int i = 0; i < found_plugins.size(); i++) {
|
||||||
|
@ -139,8 +136,11 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_itunes_sharing"), false));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_itunes_sharing"), false));
|
||||||
|
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photolibrary_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
|
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with Retina display
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with Retina display
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone with Retina HD display
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone with Retina HD display
|
||||||
|
@ -200,8 +200,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
|
||||||
strnew += lines[i].replace("$modules_buildgrp", p_config.modules_buildgrp) + "\n";
|
strnew += lines[i].replace("$modules_buildgrp", p_config.modules_buildgrp) + "\n";
|
||||||
} else if (lines[i].find("$name") != -1) {
|
} else if (lines[i].find("$name") != -1) {
|
||||||
strnew += lines[i].replace("$name", p_config.pkg_name) + "\n";
|
strnew += lines[i].replace("$name", p_config.pkg_name) + "\n";
|
||||||
} else if (lines[i].find("$info") != -1) {
|
|
||||||
strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n";
|
|
||||||
} else if (lines[i].find("$bundle_identifier") != -1) {
|
} else if (lines[i].find("$bundle_identifier") != -1) {
|
||||||
strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
|
strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
|
||||||
} else if (lines[i].find("$short_version") != -1) {
|
} else if (lines[i].find("$short_version") != -1) {
|
||||||
|
@ -210,8 +208,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
|
||||||
strnew += lines[i].replace("$version", p_preset->get("application/version")) + "\n";
|
strnew += lines[i].replace("$version", p_preset->get("application/version")) + "\n";
|
||||||
} else if (lines[i].find("$signature") != -1) {
|
} else if (lines[i].find("$signature") != -1) {
|
||||||
strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n";
|
strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n";
|
||||||
} else if (lines[i].find("$copyright") != -1) {
|
|
||||||
strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n";
|
|
||||||
} else if (lines[i].find("$team_id") != -1) {
|
} else if (lines[i].find("$team_id") != -1) {
|
||||||
strnew += lines[i].replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n";
|
strnew += lines[i].replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n";
|
||||||
} else if (lines[i].find("$default_build_config") != -1) {
|
} else if (lines[i].find("$default_build_config") != -1) {
|
||||||
|
@ -1470,9 +1466,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
|
||||||
|
|
||||||
print_line("Static framework: " + library_to_use);
|
print_line("Static framework: " + library_to_use);
|
||||||
String pkg_name;
|
String pkg_name;
|
||||||
if (p_preset->get("application/name") != "") {
|
if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
|
||||||
pkg_name = p_preset->get("application/name"); // app_name
|
|
||||||
} else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
|
|
||||||
pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
|
pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
|
||||||
} else {
|
} else {
|
||||||
pkg_name = "Unnamed";
|
pkg_name = "Unnamed";
|
||||||
|
@ -1623,24 +1617,45 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
|
||||||
return ERR_FILE_NOT_FOUND;
|
return ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
|
||||||
|
Dictionary camera_usage_descriptions = p_preset->get("privacy/camera_usage_description_localized");
|
||||||
|
Dictionary microphone_usage_descriptions = p_preset->get("privacy/microphone_usage_description_localized");
|
||||||
|
Dictionary photolibrary_usage_descriptions = p_preset->get("privacy/photolibrary_usage_description_localized");
|
||||||
|
|
||||||
Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
|
Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
|
||||||
if (translations.size() > 0) {
|
if (translations.size() > 0) {
|
||||||
{
|
{
|
||||||
String fname = dest_dir + binary_name + "/en.lproj";
|
String fname = dest_dir + binary_name + "/en.lproj";
|
||||||
tmp_app_path->make_dir_recursive(fname);
|
tmp_app_path->make_dir_recursive(fname);
|
||||||
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
|
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
|
||||||
|
f->store_line("/* Localized versions of Info.plist keys */");
|
||||||
|
f->store_line("");
|
||||||
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
|
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
|
||||||
|
f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";");
|
||||||
|
f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";");
|
||||||
|
f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photolibrary_usage_description").operator String() + "\";");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const String &E : translations) {
|
for (const String &E : translations) {
|
||||||
Ref<Translation> tr = ResourceLoader::load(E);
|
Ref<Translation> tr = ResourceLoader::load(E);
|
||||||
if (tr.is_valid()) {
|
if (tr.is_valid()) {
|
||||||
String fname = dest_dir + binary_name + "/" + tr->get_locale() + ".lproj";
|
String lang = tr->get_locale();
|
||||||
|
String fname = dest_dir + binary_name + "/" + lang + ".lproj";
|
||||||
tmp_app_path->make_dir_recursive(fname);
|
tmp_app_path->make_dir_recursive(fname);
|
||||||
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
|
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
|
||||||
String prop = "application/config/name_" + tr->get_locale();
|
f->store_line("/* Localized versions of Info.plist keys */");
|
||||||
if (ProjectSettings::get_singleton()->has_setting(prop)) {
|
f->store_line("");
|
||||||
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get(prop).operator String() + "\";");
|
if (appnames.has(lang)) {
|
||||||
|
f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (camera_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (microphone_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (photolibrary_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSPhotoLibraryUsageDescription = \"" + photolibrary_usage_descriptions[lang].operator String() + "\";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,8 +72,6 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
|
||||||
|
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
|
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
|
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), ""));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
|
||||||
|
@ -81,18 +79,30 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "application/copyright_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), false));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), false));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/location_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the location information"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/location_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the location information"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/location_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/address_book_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the address book"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/address_book_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the address book"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/address_book_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/calendar_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the calendar"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/calendar_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the calendar"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/calendar_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photos_library_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the photo library"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photos_library_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the photo library"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photos_library_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/desktop_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Desktop folder"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/desktop_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Desktop folder"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/desktop_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/documents_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Documents folder"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/documents_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Documents folder"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/documents_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/downloads_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Downloads folder"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/downloads_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Downloads folder"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/downloads_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/network_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use network volumes"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/network_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use network volumes"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/network_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/removable_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use removable volumes"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/removable_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use removable volumes"), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/removable_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
|
||||||
|
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), true));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), true));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), ""));
|
||||||
|
@ -316,9 +326,7 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
|
||||||
if (lines[i].find("$binary") != -1) {
|
if (lines[i].find("$binary") != -1) {
|
||||||
strnew += lines[i].replace("$binary", p_binary) + "\n";
|
strnew += lines[i].replace("$binary", p_binary) + "\n";
|
||||||
} else if (lines[i].find("$name") != -1) {
|
} else if (lines[i].find("$name") != -1) {
|
||||||
strnew += lines[i].replace("$name", p_binary) + "\n";
|
strnew += lines[i].replace("$name", ProjectSettings::get_singleton()->get("application/config/name")) + "\n";
|
||||||
} else if (lines[i].find("$info") != -1) {
|
|
||||||
strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n";
|
|
||||||
} else if (lines[i].find("$bundle_identifier") != -1) {
|
} else if (lines[i].find("$bundle_identifier") != -1) {
|
||||||
strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
|
strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
|
||||||
} else if (lines[i].find("$short_version") != -1) {
|
} else if (lines[i].find("$short_version") != -1) {
|
||||||
|
@ -713,9 +721,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
|
||||||
String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".64";
|
String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".64";
|
||||||
|
|
||||||
String pkg_name;
|
String pkg_name;
|
||||||
if (p_preset->get("application/name") != "") {
|
if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
|
||||||
pkg_name = p_preset->get("application/name"); // app_name
|
|
||||||
} else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
|
|
||||||
pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
|
pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
|
||||||
} else {
|
} else {
|
||||||
pkg_name = "Unnamed";
|
pkg_name = "Unnamed";
|
||||||
|
@ -781,24 +787,112 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
|
||||||
err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
|
err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
|
||||||
|
Dictionary microphone_usage_descriptions = p_preset->get("privacy/microphone_usage_description_localized");
|
||||||
|
Dictionary camera_usage_descriptions = p_preset->get("privacy/camera_usage_description_localized");
|
||||||
|
Dictionary location_usage_descriptions = p_preset->get("privacy/location_usage_description_localized");
|
||||||
|
Dictionary address_book_usage_descriptions = p_preset->get("privacy/address_book_usage_description_localized");
|
||||||
|
Dictionary calendar_usage_descriptions = p_preset->get("privacy/calendar_usage_description_localized");
|
||||||
|
Dictionary photos_library_usage_descriptions = p_preset->get("privacy/photos_library_usage_description_localized");
|
||||||
|
Dictionary desktop_folder_usage_descriptions = p_preset->get("privacy/desktop_folder_usage_description_localized");
|
||||||
|
Dictionary documents_folder_usage_descriptions = p_preset->get("privacy/documents_folder_usage_description_localized");
|
||||||
|
Dictionary downloads_folder_usage_descriptions = p_preset->get("privacy/downloads_folder_usage_description_localized");
|
||||||
|
Dictionary network_volumes_usage_descriptions = p_preset->get("privacy/network_volumes_usage_description_localized");
|
||||||
|
Dictionary removable_volumes_usage_descriptions = p_preset->get("privacy/removable_volumes_usage_description_localized");
|
||||||
|
Dictionary copyrights = p_preset->get("application/copyright_localized");
|
||||||
|
|
||||||
Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
|
Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
|
||||||
if (translations.size() > 0) {
|
if (translations.size() > 0) {
|
||||||
{
|
{
|
||||||
String fname = tmp_app_path_name + "/Contents/Resources/en.lproj";
|
String fname = tmp_app_path_name + "/Contents/Resources/en.lproj";
|
||||||
tmp_app_dir->make_dir_recursive(fname);
|
tmp_app_dir->make_dir_recursive(fname);
|
||||||
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
|
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
|
||||||
|
f->store_line("/* Localized versions of Info.plist keys */");
|
||||||
|
f->store_line("");
|
||||||
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
|
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
|
||||||
|
if (!((String)p_preset->get("privacy/microphone_usage_description")).is_empty()) {
|
||||||
|
f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (!((String)p_preset->get("privacy/camera_usage_description")).is_empty()) {
|
||||||
|
f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (!((String)p_preset->get("privacy/location_usage_description")).is_empty()) {
|
||||||
|
f->store_line("NSLocationUsageDescription = \"" + p_preset->get("privacy/location_usage_description").operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (!((String)p_preset->get("privacy/address_book_usage_description")).is_empty()) {
|
||||||
|
f->store_line("NSContactsUsageDescription = \"" + p_preset->get("privacy/address_book_usage_description").operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (!((String)p_preset->get("privacy/calendar_usage_description")).is_empty()) {
|
||||||
|
f->store_line("NSCalendarsUsageDescription = \"" + p_preset->get("privacy/calendar_usage_description").operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (!((String)p_preset->get("privacy/photos_library_usage_description")).is_empty()) {
|
||||||
|
f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photos_library_usage_description").operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (!((String)p_preset->get("privacy/desktop_folder_usage_description")).is_empty()) {
|
||||||
|
f->store_line("NSDesktopFolderUsageDescription = \"" + p_preset->get("privacy/desktop_folder_usage_description").operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (!((String)p_preset->get("privacy/documents_folder_usage_description")).is_empty()) {
|
||||||
|
f->store_line("NSDocumentsFolderUsageDescription = \"" + p_preset->get("privacy/documents_folder_usage_description").operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (!((String)p_preset->get("privacy/downloads_folder_usage_description")).is_empty()) {
|
||||||
|
f->store_line("NSDownloadsFolderUsageDescription = \"" + p_preset->get("privacy/downloads_folder_usage_description").operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (!((String)p_preset->get("privacy/network_volumes_usage_description")).is_empty()) {
|
||||||
|
f->store_line("NSNetworkVolumesUsageDescription = \"" + p_preset->get("privacy/network_volumes_usage_description").operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (!((String)p_preset->get("privacy/removable_volumes_usage_description")).is_empty()) {
|
||||||
|
f->store_line("NSRemovableVolumesUsageDescription = \"" + p_preset->get("privacy/removable_volumes_usage_description").operator String() + "\";");
|
||||||
|
}
|
||||||
|
f->store_line("NSHumanReadableCopyright = \"" + p_preset->get("application/copyright").operator String() + "\";");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const String &E : translations) {
|
for (const String &E : translations) {
|
||||||
Ref<Translation> tr = ResourceLoader::load(E);
|
Ref<Translation> tr = ResourceLoader::load(E);
|
||||||
if (tr.is_valid()) {
|
if (tr.is_valid()) {
|
||||||
String fname = tmp_app_path_name + "/Contents/Resources/" + tr->get_locale() + ".lproj";
|
String lang = tr->get_locale();
|
||||||
|
String fname = tmp_app_path_name + "/Contents/Resources/" + lang + ".lproj";
|
||||||
tmp_app_dir->make_dir_recursive(fname);
|
tmp_app_dir->make_dir_recursive(fname);
|
||||||
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
|
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
|
||||||
String prop = "application/config/name_" + tr->get_locale();
|
f->store_line("/* Localized versions of Info.plist keys */");
|
||||||
if (ProjectSettings::get_singleton()->has_setting(prop)) {
|
f->store_line("");
|
||||||
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get(prop).operator String() + "\";");
|
if (appnames.has(lang)) {
|
||||||
|
f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (microphone_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (camera_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (location_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSLocationUsageDescription = \"" + location_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (address_book_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSContactsUsageDescription = \"" + address_book_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (calendar_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSCalendarsUsageDescription = \"" + calendar_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (photos_library_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSPhotoLibraryUsageDescription = \"" + photos_library_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (desktop_folder_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSDesktopFolderUsageDescription = \"" + desktop_folder_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (documents_folder_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSDocumentsFolderUsageDescription = \"" + documents_folder_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (downloads_folder_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSDownloadsFolderUsageDescription = \"" + downloads_folder_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (network_volumes_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSNetworkVolumesUsageDescription = \"" + network_volumes_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (removable_volumes_usage_descriptions.has(lang)) {
|
||||||
|
f->store_line("NSRemovableVolumesUsageDescription = \"" + removable_volumes_usage_descriptions[lang].operator String() + "\";");
|
||||||
|
}
|
||||||
|
if (copyrights.has(lang)) {
|
||||||
|
f->store_line("NSHumanReadableCopyright = \"" + copyrights[lang].operator String() + "\";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue