2023-01-05 13:25:55 +01:00
/**************************************************************************/
/* editor_settings.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-10 02:10:30 +01:00
# include "editor_settings.h"
2017-01-16 08:04:19 +01:00
2020-11-07 23:33:38 +01:00
# include "core/config/project_settings.h"
2022-02-14 14:00:03 +01:00
# include "core/input/input_event.h"
2020-12-07 12:31:51 +01:00
# include "core/input/input_map.h"
2022-02-14 14:00:03 +01:00
# include "core/input/shortcut.h"
2018-09-15 14:45:54 +02:00
# include "core/io/certs_compressed.gen.h"
2021-06-11 14:51:48 +02:00
# include "core/io/dir_access.h"
# include "core/io/file_access.h"
2019-12-24 08:17:23 +01:00
# include "core/io/ip.h"
2017-08-26 17:46:49 +02:00
# include "core/io/resource_loader.h"
# include "core/io/resource_saver.h"
2022-02-14 14:00:03 +01:00
# include "core/object/class_db.h"
2017-08-26 17:46:49 +02:00
# include "core/os/keyboard.h"
# include "core/os/os.h"
2022-02-14 14:00:03 +01:00
# include "core/string/translation.h"
2017-08-26 17:46:49 +02:00
# include "core/version.h"
# include "editor/editor_node.h"
2022-02-14 14:00:03 +01:00
# include "editor/editor_paths.h"
2021-12-15 16:01:06 +01:00
# include "editor/editor_translation.h"
2014-02-10 02:10:30 +01:00
# include "scene/main/node.h"
2017-06-27 03:58:03 +02:00
# include "scene/main/scene_tree.h"
2020-03-04 02:51:12 +01:00
# include "scene/main/window.h"
2014-02-10 02:10:30 +01:00
2017-10-28 15:40:55 +02:00
// PRIVATE METHODS
2014-02-10 02:10:30 +01:00
2020-04-02 01:20:12 +02:00
Ref < EditorSettings > EditorSettings : : singleton = nullptr ;
2014-02-10 02:10:30 +01:00
2017-10-28 15:40:55 +02:00
// Properties
2014-02-10 02:10:30 +01:00
2018-01-06 12:40:43 +01:00
bool EditorSettings : : _set ( const StringName & p_name , const Variant & p_value ) {
_THREAD_SAFE_METHOD_
bool changed = _set_only ( p_name , p_value ) ;
if ( changed ) {
2021-10-15 14:34:11 +02:00
changed_settings . insert ( p_name ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " settings_changed " ) ) ;
2018-01-06 12:40:43 +01:00
}
return true ;
}
bool EditorSettings : : _set_only ( const StringName & p_name , const Variant & p_value ) {
2014-02-10 02:10:30 +01:00
_THREAD_SAFE_METHOD_
2016-06-05 02:31:29 +02:00
2020-12-07 12:31:51 +01:00
if ( p_name = = " shortcuts " ) {
2016-06-05 02:31:29 +02:00
Array arr = p_value ;
2021-06-21 03:34:50 +02:00
for ( int i = 0 ; i < arr . size ( ) ; i + + ) {
Dictionary dict = arr [ i ] ;
2022-09-29 11:53:28 +02:00
String shortcut_name = dict [ " name " ] ;
2021-06-21 03:34:50 +02:00
Array shortcut_events = dict [ " shortcuts " ] ;
2016-06-05 02:31:29 +02:00
2020-09-09 21:53:24 +02:00
Ref < Shortcut > sc ;
2021-06-18 00:03:09 +02:00
sc . instantiate ( ) ;
2021-06-21 03:34:50 +02:00
sc - > set_events ( shortcut_events ) ;
2022-09-29 11:53:28 +02:00
add_shortcut ( shortcut_name , sc ) ;
2016-06-05 02:31:29 +02:00
}
2020-12-07 12:31:51 +01:00
return false ;
} else if ( p_name = = " builtin_action_overrides " ) {
Array actions_arr = p_value ;
for ( int i = 0 ; i < actions_arr . size ( ) ; i + + ) {
Dictionary action_dict = actions_arr [ i ] ;
2022-09-29 11:53:28 +02:00
String action_name = action_dict [ " name " ] ;
2020-12-07 12:31:51 +01:00
Array events = action_dict [ " events " ] ;
InputMap * im = InputMap : : get_singleton ( ) ;
2022-09-29 11:53:28 +02:00
im - > action_erase_events ( action_name ) ;
2020-12-07 12:31:51 +01:00
2022-09-29 11:53:28 +02:00
builtin_action_overrides [ action_name ] . clear ( ) ;
2020-12-07 12:31:51 +01:00
for ( int ev_idx = 0 ; ev_idx < events . size ( ) ; ev_idx + + ) {
2022-09-29 11:53:28 +02:00
im - > action_add_event ( action_name , events [ ev_idx ] ) ;
builtin_action_overrides [ action_name ] . push_back ( events [ ev_idx ] ) ;
2020-12-07 12:31:51 +01:00
}
}
2018-01-06 12:40:43 +01:00
return false ;
2016-06-05 02:31:29 +02:00
}
2017-12-29 11:03:29 +01:00
bool changed = false ;
2017-11-30 04:11:53 +01:00
if ( p_value . get_type ( ) = = Variant : : NIL ) {
2017-12-29 11:03:29 +01:00
if ( props . has ( p_name ) ) {
props . erase ( p_name ) ;
changed = true ;
}
2017-11-30 04:11:53 +01:00
} else {
2017-12-29 11:03:29 +01:00
if ( props . has ( p_name ) ) {
if ( p_value ! = props [ p_name ] . variant ) {
props [ p_name ] . variant = p_value ;
changed = true ;
}
} else {
2014-02-10 02:10:30 +01:00
props [ p_name ] = VariantContainer ( p_value , last_order + + ) ;
2017-12-29 11:03:29 +01:00
changed = true ;
}
2016-06-12 02:16:14 +02:00
if ( save_changed_setting ) {
2019-06-26 15:08:25 +02:00
if ( ! props [ p_name ] . save ) {
2017-12-29 11:03:29 +01:00
props [ p_name ] . save = true ;
changed = true ;
}
2016-06-12 02:16:14 +02:00
}
2014-02-10 02:10:30 +01:00
}
2018-01-06 12:40:43 +01:00
return changed ;
2014-02-10 02:10:30 +01:00
}
2017-08-26 17:46:49 +02:00
2014-02-10 02:10:30 +01:00
bool EditorSettings : : _get ( const StringName & p_name , Variant & r_ret ) const {
_THREAD_SAFE_METHOD_
2020-12-07 12:31:51 +01:00
if ( p_name = = " shortcuts " ) {
2021-06-21 03:34:50 +02:00
Array save_array ;
2022-05-08 10:09:19 +02:00
const HashMap < String , List < Ref < InputEvent > > > & builtin_list = InputMap : : get_singleton ( ) - > get_builtins ( ) ;
2021-06-21 03:34:50 +02:00
for ( const KeyValue < String , Ref < Shortcut > > & shortcut_definition : shortcuts ) {
Ref < Shortcut > sc = shortcut_definition . value ;
2016-06-05 02:31:29 +02:00
2021-10-13 04:33:53 +02:00
if ( builtin_list . has ( shortcut_definition . key ) ) {
2020-12-07 12:31:51 +01:00
// This shortcut was auto-generated from built in actions: don't save.
Fix various typos
Found via ` codespell -q 3 -S ./thirdparty,*.po,./DONORS.md -L ackward,ang,ans,ba,beng,cas,childs,childrens,dof,doubleclick,expct,fave,findn,gird,hist,inout,leapyear,lod,nd,numer,ois,ony,paket,seeked,sinc,switchs,te,uint,varn`
Update editor/import/resource_importer_layered_texture.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update doc/classes/TileSetScenesCollectionSource.xml
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update scene/gui/graph_edit.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update scene/resources/animation.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update scene/resources/animation.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update scene/resources/animation.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update scene/gui/rich_text_label.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Revert previously committed change
2022-01-02 07:03:58 +01:00
// If the builtin is overridden, it will be saved in the "builtin_action_overrides" section below.
2020-12-07 12:31:51 +01:00
continue ;
}
2021-10-13 04:33:53 +02:00
Array shortcut_events = sc - > get_events ( ) ;
Dictionary dict ;
dict [ " name " ] = shortcut_definition . key ;
dict [ " shortcuts " ] = shortcut_events ;
if ( ! sc - > has_meta ( " original " ) ) {
// Getting the meta when it doesn't exist will return an empty array. If the 'shortcut_events' have been cleared,
2022-11-01 15:29:38 +01:00
// we still want save the shortcut in this case so that shortcuts that the user has customized are not reset,
2021-10-13 04:33:53 +02:00
// even if the 'original' has not been populated yet. This can happen when calling save() from the Project Manager.
save_array . push_back ( dict ) ;
continue ;
2021-06-21 03:34:50 +02:00
}
2016-07-04 00:13:45 +02:00
2021-06-21 03:34:50 +02:00
Array original_events = sc - > get_meta ( " original " ) ;
bool is_same = Shortcut : : is_event_array_equal ( original_events , shortcut_events ) ;
if ( is_same ) {
continue ; // Not changed from default; don't save.
2016-07-04 00:13:45 +02:00
}
2021-06-21 03:34:50 +02:00
save_array . push_back ( dict ) ;
2016-06-05 02:31:29 +02:00
}
2021-06-21 03:34:50 +02:00
r_ret = save_array ;
2016-06-05 02:31:29 +02:00
return true ;
2020-12-07 12:31:51 +01:00
} else if ( p_name = = " builtin_action_overrides " ) {
Array actions_arr ;
2021-06-21 03:34:50 +02:00
for ( const KeyValue < String , List < Ref < InputEvent > > > & action_override : builtin_action_overrides ) {
List < Ref < InputEvent > > events = action_override . value ;
2020-12-07 12:31:51 +01:00
Dictionary action_dict ;
2021-06-21 03:34:50 +02:00
action_dict [ " name " ] = action_override . key ;
2020-12-07 12:31:51 +01:00
2021-06-21 03:34:50 +02:00
// Convert the list to an array, and only keep key events as this is for the editor.
2020-12-07 12:31:51 +01:00
Array events_arr ;
2021-06-21 03:34:50 +02:00
for ( const Ref < InputEvent > & ie : events ) {
Ref < InputEventKey > iek = ie ;
if ( iek . is_valid ( ) ) {
events_arr . append ( iek ) ;
}
2020-12-07 12:31:51 +01:00
}
2021-06-21 03:34:50 +02:00
Array defaults_arr ;
List < Ref < InputEvent > > defaults = InputMap : : get_singleton ( ) - > get_builtins ( ) [ action_override . key ] ;
for ( const Ref < InputEvent > & default_input_event : defaults ) {
if ( default_input_event . is_valid ( ) ) {
defaults_arr . append ( default_input_event ) ;
}
}
bool same = Shortcut : : is_event_array_equal ( events_arr , defaults_arr ) ;
2020-12-07 12:31:51 +01:00
2021-06-21 03:34:50 +02:00
// Don't save if same as default.
if ( same ) {
continue ;
}
action_dict [ " events " ] = events_arr ;
2020-12-07 12:31:51 +01:00
actions_arr . push_back ( action_dict ) ;
}
r_ret = actions_arr ;
return true ;
2016-06-05 02:31:29 +02:00
}
2014-02-10 02:10:30 +01:00
const VariantContainer * v = props . getptr ( p_name ) ;
2017-01-05 23:41:36 +01:00
if ( ! v ) {
2019-11-07 09:44:15 +01:00
WARN_PRINT ( " EditorSettings::_get - Property not found: " + String ( p_name ) ) ;
2014-02-10 02:10:30 +01:00
return false ;
2017-01-05 23:41:36 +01:00
}
2014-02-10 02:10:30 +01:00
r_ret = v - > variant ;
return true ;
}
2017-09-25 05:26:41 +02:00
void EditorSettings : : _initial_set ( const StringName & p_name , const Variant & p_value ) {
set ( p_name , p_value ) ;
props [ p_name ] . initial = p_value ;
2017-11-20 18:34:13 +01:00
props [ p_name ] . has_default_value = true ;
2017-09-25 05:26:41 +02:00
}
2014-02-10 02:10:30 +01:00
struct _EVCSort {
String name ;
2020-11-24 10:12:55 +01:00
Variant : : Type type = Variant : : Type : : NIL ;
int order = 0 ;
bool save = false ;
bool restart_if_changed = false ;
2014-02-10 02:10:30 +01:00
bool operator < ( const _EVCSort & p_vcs ) const { return order < p_vcs . order ; }
} ;
void EditorSettings : : _get_property_list ( List < PropertyInfo > * p_list ) const {
_THREAD_SAFE_METHOD_
2022-05-13 15:04:37 +02:00
RBSet < _EVCSort > vclist ;
2014-02-10 02:10:30 +01:00
2022-05-08 10:09:19 +02:00
for ( const KeyValue < String , VariantContainer > & E : props ) {
const VariantContainer * v = & E . value ;
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( v - > hide_from_editor ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
_EVCSort vc ;
2022-05-08 10:09:19 +02:00
vc . name = E . key ;
2014-02-10 02:10:30 +01:00
vc . order = v - > order ;
vc . type = v - > variant . get_type ( ) ;
2016-06-12 02:16:14 +02:00
vc . save = v - > save ;
2019-03-06 16:10:36 +01:00
/*if (vc.save) { this should be implemented, but lets do after 3.1 is out.
if ( v - > initial . get_type ( ) ! = Variant : : NIL & & v - > initial = = v - > variant ) {
vc . save = false ;
}
} */
2018-07-19 23:58:15 +02:00
vc . restart_if_changed = v - > restart_if_changed ;
2014-02-10 02:10:30 +01:00
vclist . insert ( vc ) ;
}
2022-05-19 01:43:40 +02:00
for ( const _EVCSort & E : vclist ) {
2021-07-01 03:24:34 +02:00
uint32_t pusage = PROPERTY_USAGE_NONE ;
2022-05-19 01:43:40 +02:00
if ( E . save | | ! optimize_save ) {
2021-07-01 03:24:34 +02:00
pusage | = PROPERTY_USAGE_STORAGE ;
2016-06-12 02:16:14 +02:00
}
2022-05-19 01:43:40 +02:00
if ( ! E . name . begins_with ( " _ " ) & & ! E . name . begins_with ( " projects/ " ) ) {
2021-07-01 03:24:34 +02:00
pusage | = PROPERTY_USAGE_EDITOR ;
2016-06-12 02:16:14 +02:00
} else {
2021-07-01 03:24:34 +02:00
pusage | = PROPERTY_USAGE_STORAGE ; //hiddens must always be saved
2016-06-12 02:16:14 +02:00
}
2014-02-10 02:10:30 +01:00
2022-05-19 01:43:40 +02:00
PropertyInfo pi ( E . type , E . name ) ;
2021-07-01 03:24:34 +02:00
pi . usage = pusage ;
2022-05-19 01:43:40 +02:00
if ( hints . has ( E . name ) ) {
pi = hints [ E . name ] ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2022-05-19 01:43:40 +02:00
if ( E . restart_if_changed ) {
2018-07-19 23:58:15 +02:00
pi . usage | = PROPERTY_USAGE_RESTART_IF_CHANGED ;
}
2014-02-10 02:10:30 +01:00
p_list - > push_back ( pi ) ;
}
2016-06-05 02:31:29 +02:00
2021-11-03 23:06:17 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : ARRAY , " shortcuts " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL ) ) ; //do not edit
p_list - > push_back ( PropertyInfo ( Variant : : ARRAY , " builtin_action_overrides " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-10-28 15:40:55 +02:00
void EditorSettings : : _add_property_info_bind ( const Dictionary & p_info ) {
ERR_FAIL_COND ( ! p_info . has ( " name " ) ) ;
ERR_FAIL_COND ( ! p_info . has ( " type " ) ) ;
2017-10-05 20:34:34 +02:00
2017-10-28 15:40:55 +02:00
PropertyInfo pinfo ;
pinfo . name = p_info [ " name " ] ;
ERR_FAIL_COND ( ! props . has ( pinfo . name ) ) ;
pinfo . type = Variant : : Type ( p_info [ " type " ] . operator int ( ) ) ;
ERR_FAIL_INDEX ( pinfo . type , Variant : : VARIANT_MAX ) ;
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( p_info . has ( " hint " ) ) {
2017-10-28 15:40:55 +02:00
pinfo . hint = PropertyHint ( p_info [ " hint " ] . operator int ( ) ) ;
2020-05-14 16:41:43 +02:00
}
if ( p_info . has ( " hint_string " ) ) {
2017-10-28 15:40:55 +02:00
pinfo . hint_string = p_info [ " hint_string " ] ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-10-28 15:40:55 +02:00
add_property_hint ( pinfo ) ;
2014-02-10 02:10:30 +01:00
}
2017-10-28 15:40:55 +02:00
// Default configs
2017-10-28 23:25:28 +02:00
bool EditorSettings : : has_default_value ( const String & p_setting ) const {
_THREAD_SAFE_METHOD_
2020-05-14 16:41:43 +02:00
if ( ! props . has ( p_setting ) ) {
2017-10-28 23:25:28 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2017-11-20 18:34:13 +01:00
return props [ p_setting ] . has_default_value ;
2017-10-28 23:25:28 +02:00
}
2014-02-10 02:10:30 +01:00
2017-10-28 15:40:55 +02:00
void EditorSettings : : _load_defaults ( Ref < ConfigFile > p_extra_config ) {
2014-02-10 02:10:30 +01:00
_THREAD_SAFE_METHOD_
2021-08-16 07:30:24 +02:00
// Sets up the editor setting with a default value and hint PropertyInfo.
# define EDITOR_SETTING(m_type, m_property_hint, m_name, m_default_value, m_hint_string) \
_initial_set ( m_name , m_default_value ) ; \
hints [ m_name ] = PropertyInfo ( m_type , m_name , m_property_hint , m_hint_string ) ;
# define EDITOR_SETTING_USAGE(m_type, m_property_hint, m_name, m_default_value, m_hint_string, m_usage) \
_initial_set ( m_name , m_default_value ) ; \
hints [ m_name ] = PropertyInfo ( m_type , m_name , m_property_hint , m_hint_string , m_usage ) ;
2014-02-10 02:10:30 +01:00
2018-12-12 08:18:24 +01:00
/* Languages */
2017-10-28 15:40:55 +02:00
{
String lang_hint = " en " ;
String host_lang = OS : : get_singleton ( ) - > get_locale ( ) ;
2014-02-10 02:10:30 +01:00
2020-09-03 13:22:16 +02:00
// Skip locales if Text server lack required features.
Vector < String > locales_to_skip ;
if ( ! TS - > has_feature ( TextServer : : FEATURE_BIDI_LAYOUT ) | | ! TS - > has_feature ( TextServer : : FEATURE_SHAPING ) ) {
locales_to_skip . push_back ( " ar " ) ; // Arabic
locales_to_skip . push_back ( " fa " ) ; // Persian
locales_to_skip . push_back ( " ur " ) ; // Urdu
}
if ( ! TS - > has_feature ( TextServer : : FEATURE_BIDI_LAYOUT ) ) {
locales_to_skip . push_back ( " he " ) ; // Hebrew
}
if ( ! TS - > has_feature ( TextServer : : FEATURE_SHAPING ) ) {
locales_to_skip . push_back ( " bn " ) ; // Bengali
locales_to_skip . push_back ( " hi " ) ; // Hindi
locales_to_skip . push_back ( " ml " ) ; // Malayalam
locales_to_skip . push_back ( " si " ) ; // Sinhala
locales_to_skip . push_back ( " ta " ) ; // Tamil
locales_to_skip . push_back ( " te " ) ; // Telugu
}
2019-05-21 14:32:01 +02:00
2020-12-15 13:04:21 +01:00
if ( ! locales_to_skip . is_empty ( ) ) {
2020-09-03 13:22:16 +02:00
WARN_PRINT ( " Some locales are not properly supported by selected Text Server and are disabled. " ) ;
}
2017-09-25 05:26:41 +02:00
2020-09-03 13:22:16 +02:00
String best ;
2021-09-23 13:08:50 +02:00
int best_score = 0 ;
2021-12-15 16:01:06 +01:00
for ( const String & locale : get_editor_locales ( ) ) {
2019-05-21 14:32:01 +02:00
// Skip locales which we can't render properly (see above comment).
// Test against language code without regional variants (e.g. ur_PK).
String lang_code = locale . get_slice ( " _ " , 0 ) ;
2022-02-01 19:19:13 +01:00
if ( locales_to_skip . has ( lang_code ) ) {
2019-05-21 14:32:01 +02:00
continue ;
}
2017-10-28 15:40:55 +02:00
lang_hint + = " , " ;
lang_hint + = locale ;
2014-02-10 02:10:30 +01:00
2021-09-23 13:08:50 +02:00
int score = TranslationServer : : get_singleton ( ) - > compare_locales ( host_lang , locale ) ;
2022-01-24 17:58:16 +01:00
if ( score > 0 & & score > = best_score ) {
2017-10-28 15:40:55 +02:00
best = locale ;
2021-09-23 13:08:50 +02:00
best_score = score ;
2017-10-28 15:40:55 +02:00
}
}
2021-09-23 13:08:50 +02:00
if ( best_score = = 0 ) {
2017-10-28 15:40:55 +02:00
best = " en " ;
}
2017-08-03 18:23:46 +02:00
2021-08-16 07:30:24 +02:00
EDITOR_SETTING_USAGE ( Variant : : STRING , PROPERTY_HINT_ENUM , " interface/editor/editor_language " , best , lang_hint , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED ) ;
2017-10-28 15:40:55 +02:00
}
2017-08-03 18:23:46 +02:00
2018-12-12 08:18:24 +01:00
/* Interface */
// Editor
2021-01-18 02:39:46 +01:00
// Display what the Auto display scale setting effectively corresponds to.
2021-08-16 07:30:24 +02:00
const String display_scale_hint_string = vformat ( " Auto (%d%%),75%%,100%%,125%%,150%%,175%%,200%%,Custom " , Math : : round ( get_auto_display_scale ( ) * 100 ) ) ;
EDITOR_SETTING_USAGE ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/display_scale " , 0 , display_scale_hint_string , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED )
2021-08-08 17:07:57 +02:00
2023-03-21 12:08:46 +01:00
String ed_screen_hints = " Screen With Mouse Pointer:-4,Screen With Keyboard Focus:-3,Primary Screen:-2 " ; // Note: Main Window Screen:-1 is not used for the main window.
for ( int i = 0 ; i < DisplayServer : : get_singleton ( ) - > get_screen_count ( ) ; i + + ) {
ed_screen_hints + = " ,Screen " + itos ( i + 1 ) + " : " + itos ( i ) ;
}
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/editor_screen " , - 2 , ed_screen_hints )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/project_manager_screen " , - 2 , ed_screen_hints )
2022-03-21 01:53:30 +01:00
_initial_set ( " interface/editor/debug/enable_pseudolocalization " , false ) ;
set_restart_if_changed ( " interface/editor/debug/enable_pseudolocalization " , true ) ;
2021-08-08 17:07:57 +02:00
// Use pseudolocalization in editor.
2022-08-01 11:28:16 +02:00
EDITOR_SETTING_USAGE ( Variant : : BOOL , PROPERTY_HINT_NONE , " interface/editor/use_embedded_menu " , false , " " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED )
2022-08-23 12:40:48 +02:00
EDITOR_SETTING_USAGE ( Variant : : BOOL , PROPERTY_HINT_NONE , " interface/editor/expand_to_title " , true , " " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED )
2021-08-08 17:07:57 +02:00
2021-08-16 07:30:24 +02:00
EDITOR_SETTING_USAGE ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " interface/editor/custom_display_scale " , 1.0 , " 0.5,3,0.01 " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED )
2022-03-21 07:20:09 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " interface/editor/main_font_size " , 14 , " 8,48,1 " )
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " interface/editor/code_font_size " , 14 , " 8,48,1 " )
2022-11-12 18:55:57 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/code_font_contextual_ligatures " , 1 , " Enabled,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set " )
2020-09-03 13:22:16 +02:00
_initial_set ( " interface/editor/code_font_custom_opentype_features " , " " ) ;
2020-10-22 18:40:18 +02:00
_initial_set ( " interface/editor/code_font_custom_variations " , " " ) ;
2022-11-03 18:37:21 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/font_antialiasing " , 1 , " None,Grayscale,LCD Subpixel " )
2022-07-20 08:28:22 +02:00
# ifdef MACOS_ENABLED
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/font_hinting " , 0 , " Auto (None),None,Light,Normal " )
2021-01-18 02:39:46 +01:00
# else
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/font_hinting " , 0 , " Auto (Light),None,Light,Normal " )
2021-01-18 02:39:46 +01:00
# endif
2022-11-03 18:37:21 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/font_subpixel_positioning " , 1 , " Disabled,Auto,One Half of a Pixel,One Quarter of a Pixel " )
2022-01-10 09:13:22 +01:00
2022-03-25 09:54:32 +01:00
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_GLOBAL_FILE , " interface/editor/main_font " , " " , " *.ttf,*.otf,*.woff,*.woff2,*.pfb,*.pfm " )
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_GLOBAL_FILE , " interface/editor/main_font_bold " , " " , " *.ttf,*.otf,*.woff,*.woff2,*.pfb,*.pfm " )
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_GLOBAL_FILE , " interface/editor/code_font " , " " , " *.ttf,*.otf,*.woff,*.woff2,*.pfb,*.pfm " )
2021-08-16 07:30:24 +02:00
EDITOR_SETTING_USAGE ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " interface/editor/low_processor_mode_sleep_usec " , 6900 , " 1,100000,1 " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED )
// Default unfocused usec sleep is for 10 FPS. Allow an unfocused FPS limit
// as low as 1 FPS for those who really need low power usage (but don't need
// to preview particles or shaders while the editor is unfocused). With very
// low FPS limits, the editor can take a small while to become usable after
// being focused again, so this should be used at the user's discretion.
EDITOR_SETTING_USAGE ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " interface/editor/unfocused_low_processor_mode_sleep_usec " , 100000 , " 1,1000000,1 " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED )
2017-10-28 15:40:55 +02:00
_initial_set ( " interface/editor/separate_distraction_mode " , false ) ;
2019-07-23 07:05:29 +02:00
_initial_set ( " interface/editor/automatically_open_screenshots " , true ) ;
2021-08-16 07:30:24 +02:00
EDITOR_SETTING_USAGE ( Variant : : BOOL , PROPERTY_HINT_NONE , " interface/editor/single_window_mode " , false , " " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED )
2020-03-08 17:32:49 +01:00
_initial_set ( " interface/editor/mouse_extra_buttons_navigate_history " , true ) ;
2017-10-28 15:40:55 +02:00
_initial_set ( " interface/editor/save_each_scene_on_quit " , true ) ; // Regression
2022-03-21 10:55:18 +01:00
EDITOR_SETTING_USAGE ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/accept_dialog_cancel_ok_buttons " , 0 ,
vformat ( " Auto (%s),Cancel First,OK First " , DisplayServer : : get_singleton ( ) - > get_swap_cancel_ok ( ) ? " OK First " : " Cancel First " ) ,
PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED ) ;
2022-01-08 02:32:53 +01:00
# ifdef DEV_ENABLED
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/show_internal_errors_in_toast_notifications " , 0 , " Auto (Enabled),Enabled,Disabled " )
# else
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/show_internal_errors_in_toast_notifications " , 0 , " Auto (Disabled),Enabled,Disabled " )
# endif
2017-07-12 20:46:08 +02:00
2021-01-01 19:41:11 +01:00
// Inspector
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " interface/inspector/max_array_dictionary_items_per_page " , 20 , " 10,100,1 " )
2022-05-09 11:47:10 +02:00
EDITOR_SETTING ( Variant : : BOOL , PROPERTY_HINT_NONE , " interface/inspector/show_low_level_opentype_features " , false , " " )
2021-07-21 00:45:29 +02:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " interface/inspector/float_drag_speed " , 5.0 , " 0.1,100,0.01 " )
2021-01-01 19:41:11 +01:00
2018-12-12 08:18:24 +01:00
// Theme
2022-01-29 00:09:44 +01:00
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_ENUM , " interface/theme/preset " , " Default " , " Default,Breeze Dark,Godot 2,Gray,Light,Solarized (Dark),Solarized (Light),Black (OLED),Custom " )
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/theme/icon_and_font_color " , 0 , " Auto,Dark,Light " )
EDITOR_SETTING ( Variant : : COLOR , PROPERTY_HINT_NONE , " interface/theme/base_color " , Color ( 0.2 , 0.23 , 0.31 ) , " " )
EDITOR_SETTING ( Variant : : COLOR , PROPERTY_HINT_NONE , " interface/theme/accent_color " , Color ( 0.41 , 0.61 , 0.91 ) , " " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " interface/theme/contrast " , 0.3 , " -1,1,0.01 " )
2022-01-29 00:09:44 +01:00
EDITOR_SETTING ( Variant : : BOOL , PROPERTY_HINT_NONE , " interface/theme/draw_extra_borders " , false , " " )
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " interface/theme/icon_saturation " , 1.0 , " 0,2,0.01 " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " interface/theme/relationship_line_opacity " , 0.1 , " 0.00,1,0.01 " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " interface/theme/border_size " , 0 , " 0,2,1 " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " interface/theme/corner_radius " , 3 , " 0,6,1 " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " interface/theme/additional_spacing " , 0.0 , " 0,5,0.1 " )
EDITOR_SETTING_USAGE ( Variant : : STRING , PROPERTY_HINT_GLOBAL_FILE , " interface/theme/custom_theme " , " " , " *.res,*.tres,*.theme " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED )
2017-08-03 18:23:46 +02:00
2023-02-21 18:18:08 +01:00
// Touchscreen
bool has_touchscreen_ui = DisplayServer : : get_singleton ( ) - > is_touchscreen_available ( ) ;
EDITOR_SETTING ( Variant : : BOOL , PROPERTY_HINT_NONE , " interface/touchscreen/increase_scrollbar_touch_area " , has_touchscreen_ui , " " )
EDITOR_SETTING ( Variant : : BOOL , PROPERTY_HINT_NONE , " interface/touchscreen/enable_long_press_as_right_click " , has_touchscreen_ui , " " )
set_restart_if_changed ( " interface/touchscreen/enable_long_press_as_right_click " , true ) ;
EDITOR_SETTING ( Variant : : BOOL , PROPERTY_HINT_NONE , " interface/touchscreen/enable_pan_and_scale_gestures " , has_touchscreen_ui , " " )
set_restart_if_changed ( " interface/touchscreen/enable_pan_and_scale_gestures " , true ) ;
2023-04-05 22:04:00 +02:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " interface/touchscreen/scale_gizmo_handles " , has_touchscreen_ui ? 3 : 1 , " 1,5,1 " )
2023-02-21 18:18:08 +01:00
2018-12-12 08:18:24 +01:00
// Scene tabs
2022-03-13 02:03:26 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/scene_tabs/display_close_button " , 1 , " Never,If Tab Active,Always " ) ; // TabBar::CloseButtonDisplayPolicy
2017-10-28 15:40:55 +02:00
_initial_set ( " interface/scene_tabs/show_thumbnail_on_hover " , true ) ;
2022-02-03 06:45:31 +01:00
EDITOR_SETTING_USAGE ( Variant : : INT , PROPERTY_HINT_RANGE , " interface/scene_tabs/maximum_width " , 350 , " 0,9999,1 " , PROPERTY_USAGE_DEFAULT )
2018-12-12 08:18:24 +01:00
_initial_set ( " interface/scene_tabs/show_script_button " , false ) ;
2017-08-03 18:23:46 +02:00
2022-11-02 15:23:25 +01:00
// Multi Window
EDITOR_SETTING ( Variant : : BOOL , PROPERTY_HINT_NONE , " interface/multi_window/enable " , true , " " ) ;
EDITOR_SETTING ( Variant : : BOOL , PROPERTY_HINT_NONE , " interface/multi_window/restore_windows_on_load " , true , " " ) ;
EDITOR_SETTING ( Variant : : BOOL , PROPERTY_HINT_NONE , " interface/multi_window/maximize_window " , false , " " ) ;
set_restart_if_changed ( " interface/multi_window/enable " , true ) ;
2018-12-12 08:18:24 +01:00
/* Filesystem */
2022-11-10 22:26:40 +01:00
// External Programs
2023-01-26 13:16:55 +01:00
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_GLOBAL_FILE , " filesystem/external_programs/raster_image_editor " , " " , " " )
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_GLOBAL_FILE , " filesystem/external_programs/vector_image_editor " , " " , " " )
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_GLOBAL_FILE , " filesystem/external_programs/audio_editor " , " " , " " )
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_GLOBAL_FILE , " filesystem/external_programs/3d_model_editor " , " " , " " )
2022-11-10 22:26:40 +01:00
2018-12-12 08:18:24 +01:00
// Directories
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_GLOBAL_DIR , " filesystem/directories/autoscan_project_path " , " " , " " )
const String fs_dir_default_project_path = OS : : get_singleton ( ) - > has_environment ( " HOME " ) ? OS : : get_singleton ( ) - > get_environment ( " HOME " ) : OS : : get_singleton ( ) - > get_system_dir ( OS : : SYSTEM_DIR_DOCUMENTS ) ;
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_GLOBAL_DIR , " filesystem/directories/default_project_path " , fs_dir_default_project_path , " " )
2017-07-12 20:46:08 +02:00
2018-12-12 08:18:24 +01:00
// On save
_initial_set ( " filesystem/on_save/compress_binary_resources " , true ) ;
_initial_set ( " filesystem/on_save/safe_save_on_backup_then_rename " , true ) ;
// File dialog
_initial_set ( " filesystem/file_dialog/show_hidden_files " , false ) ;
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " filesystem/file_dialog/display_mode " , 0 , " Thumbnails,List " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " filesystem/file_dialog/thumbnail_size " , 64 , " 32,128,16 " )
2018-12-12 08:18:24 +01:00
/* Docks */
// SceneTree
_initial_set ( " docks/scene_tree/start_create_dialog_fully_expanded " , false ) ;
2021-08-09 19:14:06 +02:00
_initial_set ( " docks/scene_tree/auto_expand_to_selected " , true ) ;
2018-12-12 08:18:24 +01:00
// FileSystem
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " docks/filesystem/thumbnail_size " , 64 , " 32,128,16 " )
2018-12-12 08:18:24 +01:00
_initial_set ( " docks/filesystem/always_show_folders " , true ) ;
2021-09-23 23:09:15 +02:00
_initial_set ( " docks/filesystem/textfile_extensions " , " txt,md,cfg,ini,log,json,yml,yaml,toml " ) ;
2018-12-12 08:18:24 +01:00
// Property editor
2021-02-10 21:18:45 +01:00
_initial_set ( " docks/property_editor/auto_refresh_interval " , 0.2 ) ; //update 5 times per second by default
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " docks/property_editor/subresource_hue_tint " , 0.75 , " 0,1,0.01 " )
2018-12-12 08:18:24 +01:00
/* Text editor */
// Theme
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_ENUM , " text_editor/theme/color_theme " , " Default " , " Default,Godot 2,Custom " )
2014-02-10 02:10:30 +01:00
2021-08-15 19:14:46 +02:00
// Theme: Highlighting
2021-05-27 10:22:36 +02:00
_load_godot2_text_editor_theme ( ) ;
2014-02-10 02:10:30 +01:00
2019-09-01 13:28:57 +02:00
// Appearance
2021-08-15 19:14:46 +02:00
// Appearance: Caret
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " text_editor/appearance/caret/type " , 0 , " Line,Block " )
2021-08-15 19:14:46 +02:00
_initial_set ( " text_editor/appearance/caret/caret_blink " , true ) ;
2022-08-13 14:52:35 +02:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " text_editor/appearance/caret/caret_blink_interval " , 0.5 , " 0.1,10,0.01 " )
2021-08-15 19:14:46 +02:00
_initial_set ( " text_editor/appearance/caret/highlight_current_line " , true ) ;
_initial_set ( " text_editor/appearance/caret/highlight_all_occurrences " , true ) ;
// Appearance: Guidelines
_initial_set ( " text_editor/appearance/guidelines/show_line_length_guidelines " , true ) ;
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/appearance/guidelines/line_length_guideline_soft_column " , 80 , " 20,160,1 " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/appearance/guidelines/line_length_guideline_hard_column " , 100 , " 20,160,1 " )
2021-08-15 19:14:46 +02:00
// Appearance: Gutters
_initial_set ( " text_editor/appearance/gutters/show_line_numbers " , true ) ;
_initial_set ( " text_editor/appearance/gutters/line_numbers_zero_padded " , false ) ;
_initial_set ( " text_editor/appearance/gutters/highlight_type_safe_lines " , true ) ;
_initial_set ( " text_editor/appearance/gutters/show_bookmark_gutter " , true ) ;
_initial_set ( " text_editor/appearance/gutters/show_info_gutter " , true ) ;
// Appearance: Minimap
_initial_set ( " text_editor/appearance/minimap/show_minimap " , true ) ;
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/appearance/minimap/minimap_width " , 80 , " 50,250,1 " )
2021-08-15 19:14:46 +02:00
// Appearance: Lines
_initial_set ( " text_editor/appearance/lines/code_folding " , true ) ;
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " text_editor/appearance/lines/word_wrap " , 0 , " None,Boundary " )
2021-08-15 19:14:46 +02:00
// Appearance: Whitespace
_initial_set ( " text_editor/appearance/whitespace/draw_tabs " , true ) ;
_initial_set ( " text_editor/appearance/whitespace/draw_spaces " , false ) ;
2022-03-21 02:00:58 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/appearance/whitespace/line_spacing " , 4 , " 0,50,1 " )
2021-08-15 19:14:46 +02:00
// Behavior
// Behavior: Navigation
_initial_set ( " text_editor/behavior/navigation/move_caret_on_right_click " , true ) ;
_initial_set ( " text_editor/behavior/navigation/scroll_past_end_of_file " , false ) ;
_initial_set ( " text_editor/behavior/navigation/smooth_scrolling " , true ) ;
2022-02-12 14:40:49 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/behavior/navigation/v_scroll_speed " , 80 , " 1,10000,1 " )
2022-06-19 16:55:13 +02:00
_initial_set ( " text_editor/behavior/navigation/drag_and_drop_selection " , true ) ;
2022-07-23 14:29:30 +02:00
_initial_set ( " text_editor/behavior/navigation/stay_in_script_editor_on_node_selected " , true ) ;
2021-08-15 19:14:46 +02:00
// Behavior: Indent
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " text_editor/behavior/indent/type " , 0 , " Tabs,Spaces " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/behavior/indent/size " , 4 , " 1,64,1 " ) // size of 0 crashes.
2021-08-15 19:14:46 +02:00
_initial_set ( " text_editor/behavior/indent/auto_indent " , true ) ;
// Behavior: Files
_initial_set ( " text_editor/behavior/files/trim_trailing_whitespace_on_save " , false ) ;
_initial_set ( " text_editor/behavior/files/autosave_interval_secs " , 0 ) ;
_initial_set ( " text_editor/behavior/files/restore_scripts_on_load " , true ) ;
_initial_set ( " text_editor/behavior/files/convert_indent_on_save " , true ) ;
2022-03-06 21:39:19 +01:00
_initial_set ( " text_editor/behavior/files/auto_reload_scripts_on_external_change " , false ) ;
2019-09-01 13:28:57 +02:00
// Script list
_initial_set ( " text_editor/script_list/show_members_overview " , true ) ;
2021-08-15 19:14:46 +02:00
_initial_set ( " text_editor/script_list/sort_members_outline_alphabetically " , false ) ;
2014-02-10 02:10:30 +01:00
2018-12-12 08:18:24 +01:00
// Completion
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " text_editor/completion/idle_parse_delay " , 2.0 , " 0.1,10,0.01 " )
2019-07-18 21:34:28 +02:00
_initial_set ( " text_editor/completion/auto_brace_complete " , true ) ;
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " text_editor/completion/code_complete_delay " , 0.3 , " 0.01,5,0.01 " )
2018-01-06 12:40:43 +01:00
_initial_set ( " text_editor/completion/put_callhint_tooltip_below_current_line " , true ) ;
2017-10-28 15:40:55 +02:00
_initial_set ( " text_editor/completion/complete_file_paths " , true ) ;
2018-05-30 04:16:59 +02:00
_initial_set ( " text_editor/completion/add_type_hints " , false ) ;
2018-12-18 02:53:54 +01:00
_initial_set ( " text_editor/completion/use_single_quotes " , false ) ;
2014-02-10 02:10:30 +01:00
2018-12-12 08:18:24 +01:00
// Help
_initial_set ( " text_editor/help/show_help_index " , true ) ;
2023-02-11 17:35:10 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/help/help_font_size " , 16 , " 8,48,1 " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/help/help_source_font_size " , 15 , " 8,48,1 " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/help/help_title_font_size " , 23 , " 8,64,1 " )
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " text_editor/help/class_reference_examples " , 0 , " GDScript,C#,GDScript and C# " )
2018-12-12 08:18:24 +01:00
/* Editors */
2014-02-10 02:10:30 +01:00
2018-12-12 08:18:24 +01:00
// GridMap
2017-10-28 15:40:55 +02:00
_initial_set ( " editors/grid_map/pick_distance " , 5000.0 ) ;
2014-02-10 02:10:30 +01:00
2018-12-12 08:18:24 +01:00
// 3D
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : COLOR , PROPERTY_HINT_NONE , " editors/3d/primary_grid_color " , Color ( 0.56 , 0.56 , 0.56 , 0.5 ) , " " )
EDITOR_SETTING ( Variant : : COLOR , PROPERTY_HINT_NONE , " editors/3d/secondary_grid_color " , Color ( 0.38 , 0.38 , 0.38 , 0.5 ) , " " )
2018-04-30 01:43:20 +02:00
2020-12-29 07:35:59 +01:00
// Use a similar color to the 2D editor selection.
2021-08-16 07:30:24 +02:00
EDITOR_SETTING_USAGE ( Variant : : COLOR , PROPERTY_HINT_NONE , " editors/3d/selection_box_color " , Color ( 1.0 , 0.5 , 0 ) , " " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED )
2022-03-06 21:39:19 +01:00
_initial_set ( " editors/3d_gizmos/gizmo_colors/instantiated " , Color ( 0.7 , 0.7 , 0.7 , 0.6 ) ) ;
_initial_set ( " editors/3d_gizmos/gizmo_colors/joint " , Color ( 0.5 , 0.8 , 1 ) ) ;
_initial_set ( " editors/3d_gizmos/gizmo_colors/shape " , Color ( 0.5 , 0.7 , 1 ) ) ;
2020-12-29 07:35:59 +01:00
2019-04-21 12:15:45 +02:00
// If a line is a multiple of this, it uses the primary grid color.
2020-11-21 21:35:23 +01:00
// Use a power of 2 value by default as it's more common to use powers of 2 in level design.
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " editors/3d/primary_grid_steps " , 8 , " 1,100,1 " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " editors/3d/grid_size " , 200 , " 1,2000,1 " )
2019-04-21 12:15:45 +02:00
// Higher values produce graphical artifacts when far away unless View Z-Far
// is increased significantly more than it really should need to be.
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " editors/3d/grid_division_level_max " , 2 , " -1,3,1 " )
2019-04-21 12:15:45 +02:00
// Lower values produce graphical artifacts regardless of view clipping planes, so limit to -2 as a lower bound.
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " editors/3d/grid_division_level_min " , 0 , " -2,2,1 " )
2019-04-21 12:15:45 +02:00
// -0.2 seems like a sensible default. -1.0 gives Blender-like behavior, 0.5 gives huge grids.
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/grid_division_level_bias " , - 0.2 , " -1.0,0.5,0.1 " )
2019-04-21 12:15:45 +02:00
_initial_set ( " editors/3d/grid_xz_plane " , true ) ;
_initial_set ( " editors/3d/grid_xy_plane " , false ) ;
_initial_set ( " editors/3d/grid_yz_plane " , false ) ;
2014-02-10 02:10:30 +01:00
2019-10-31 14:32:46 +01:00
// Use a lower default FOV for the 3D camera compared to the
// Camera3D node as the 3D viewport doesn't span the whole screen.
// This means it's technically viewed from a further distance, which warrants a narrower FOV.
2021-12-03 01:09:19 +01:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/default_fov " , 70.0 , " 1,179,0.1,degrees " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/default_z_near " , 0.05 , " 0.01,10,0.01,or_greater,suffix:m " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/default_z_far " , 4000.0 , " 0.1,4000,0.1,or_greater,suffix:m " )
2017-10-28 15:40:55 +02:00
2018-12-12 08:18:24 +01:00
// 3D: Navigation
2020-08-15 13:18:01 +02:00
_initial_set ( " editors/3d/navigation/invert_x_axis " , false ) ;
2021-08-16 07:30:24 +02:00
_initial_set ( " editors/3d/navigation/invert_y_axis " , false ) ;
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/3d/navigation/navigation_scheme " , 0 , " Godot,Maya,Modo " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/3d/navigation/zoom_style " , 0 , " Vertical,Horizontal " )
2017-10-28 15:40:55 +02:00
2021-07-02 09:27:12 +02:00
_initial_set ( " editors/3d/navigation/emulate_numpad " , false ) ;
2017-10-28 15:40:55 +02:00
_initial_set ( " editors/3d/navigation/emulate_3_button_mouse " , false ) ;
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/3d/navigation/orbit_modifier " , 0 , " None,Shift,Alt,Meta,Ctrl " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/3d/navigation/pan_modifier " , 1 , " None,Shift,Alt,Meta,Ctrl " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/3d/navigation/zoom_modifier " , 4 , " None,Shift,Alt,Meta,Ctrl " )
2017-10-28 15:40:55 +02:00
_initial_set ( " editors/3d/navigation/warped_mouse_panning " , true ) ;
2018-12-12 08:18:24 +01:00
// 3D: Navigation feel
2020-01-14 00:26:26 +01:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/navigation_feel/orbit_sensitivity " , 0.25 , " 0.01,2,0.001 " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/navigation_feel/orbit_inertia " , 0.0 , " 0,1,0.001 " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/navigation_feel/translation_inertia " , 0.05 , " 0,1,0.001 " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/navigation_feel/zoom_inertia " , 0.05 , " 0,1,0.001 " )
2017-10-28 15:40:55 +02:00
2018-12-12 08:18:24 +01:00
// 3D: Freelook
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/3d/freelook/freelook_navigation_scheme " , 0 , " Default,Partially Axis-Locked (id Tech),Fully Axis-Locked (Minecraft) " )
2020-01-14 00:26:26 +01:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/freelook/freelook_sensitivity " , 0.25 , " 0.01,2,0.001 " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/freelook/freelook_inertia " , 0.0 , " 0,1,0.001 " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/freelook/freelook_base_speed " , 5.0 , " 0,10,0.01 " )
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/3d/freelook/freelook_activation_modifier " , 0 , " None,Shift,Alt,Meta,Ctrl " )
2017-10-28 15:40:55 +02:00
_initial_set ( " editors/3d/freelook/freelook_speed_zoom_link " , false ) ;
2018-12-12 08:18:24 +01:00
// 2D
2018-08-18 17:32:09 +02:00
_initial_set ( " editors/2d/grid_color " , Color ( 1.0 , 1.0 , 1.0 , 0.07 ) ) ;
2017-12-05 21:42:33 +01:00
_initial_set ( " editors/2d/guides_color " , Color ( 0.6 , 0.0 , 0.8 ) ) ;
2019-04-05 10:18:21 +02:00
_initial_set ( " editors/2d/smart_snapping_line_color " , Color ( 0.9 , 0.1 , 0.1 ) ) ;
2017-10-28 15:40:55 +02:00
_initial_set ( " editors/2d/bone_width " , 5 ) ;
New and improved IK system for Skeleton2D
This PR and commit adds a new IK system for 2D with the Skeleton2D node
that adds several new IK solvers, a way to control bones in a Skeleton2D
node similar to that in Skeleton3D. It also adds additional changes
and functionality.
This work was sponsored by GSoC 2020 and TwistedTwigleg.
Full list of changes:
* Adds a SkeletonModifier2D resource
* This resource is the base where all IK code is written and executed
* Has a function for clamping angles, since it is so commonly used
* Modifiers are unique when duplicated so it works with instancing
* Adds a SkeletonModifierStack2D resource
* This resource manages a series of SkeletonModification2Ds
* This is what the Skeleton2D directly interfaces with to make IK possible
* Adds SkeletonModifier2D resources for LookAt, CCDIK, FABRIK, Jiggle, and TwoBoneIK
* Each modification is in its own file
* There is also a SkeletonModifier2D resource that acts as a stack for using multiple stacks together
* Adds a PhysicalBone2D node
* Works similar to the PhysicalBone3D node, but uses a RigidBody2D node
* Changes to Skeleton2D listed below:
* Skeleton2D now holds a single SkeletonModificationStack2D for IK
* Skeleton2D now has a local_pose_override, which overrides the Bone2D position similar to how the overrides work in Skeleton3D
* Changes to Bone2D listed below:
* The default_length property has been changed to length. Length is the length of the bone to its child bone node
* New bone_angle property, which is the angle the bone has to its first child bone node
* Bone2D caches its transform when not modified by IK for IK interpolation purposes
* Bone2D draws its own editor gizmo, though this is stated to change in the future
* Changes to CanvasItemEditor listed below:
* Bone2D gizmo drawing code removed
* The 2D IK code is removed. Now Bone2D is the only bone system for 2D
* Transform2D now has a looking_at function for rotating to face a position
* Two new node notifications: NOTIFICATION_EDITOR_PRE_SAVE and NOTIFICATION_EDITOR_POST_SAVE
* These notifications only are called in the editor right before and after saving a scene
* Needed for not saving the IK position when executing IK in the editor
* Documentation for all the changes listed above.
2020-08-03 20:02:24 +02:00
_initial_set ( " editors/2d/bone_color1 " , Color ( 1.0 , 1.0 , 1.0 , 0.7 ) ) ;
_initial_set ( " editors/2d/bone_color2 " , Color ( 0.6 , 0.6 , 0.6 , 0.7 ) ) ;
_initial_set ( " editors/2d/bone_selected_color " , Color ( 0.9 , 0.45 , 0.45 , 0.7 ) ) ;
_initial_set ( " editors/2d/bone_ik_color " , Color ( 0.9 , 0.9 , 0.45 , 0.7 ) ) ;
_initial_set ( " editors/2d/bone_outline_color " , Color ( 0.35 , 0.35 , 0.35 , 0.5 ) ) ;
2018-05-04 16:54:04 +02:00
_initial_set ( " editors/2d/bone_outline_size " , 2 ) ;
2018-09-24 15:16:40 +02:00
_initial_set ( " editors/2d/viewport_border_color " , Color ( 0.4 , 0.4 , 1.0 , 0.4 ) ) ;
2019-06-24 21:15:26 +02:00
_initial_set ( " editors/2d/constrain_editor_view " , true ) ;
2022-01-19 19:59:12 +01:00
// Panning
// Enum should be in sync with ControlScheme in ViewPanner.
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/panning/2d_editor_panning_scheme " , 0 , " Scroll Zooms,Scroll Pans " ) ;
2022-01-23 13:49:53 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/panning/sub_editors_panning_scheme " , 0 , " Scroll Zooms,Scroll Pans " ) ;
2022-01-19 19:59:12 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/panning/animation_editors_panning_scheme " , 1 , " Scroll Zooms,Scroll Pans " ) ;
_initial_set ( " editors/panning/simple_panning " , false ) ;
_initial_set ( " editors/panning/warped_mouse_panning " , true ) ;
_initial_set ( " editors/panning/2d_editor_pan_speed " , 20 ) ;
2017-10-28 15:40:55 +02:00
2021-05-21 17:28:28 +02:00
// Tiles editor
_initial_set ( " editors/tiles_editor/display_grid " , true ) ;
_initial_set ( " editors/tiles_editor/grid_color " , Color ( 1.0 , 0.5 , 0.2 , 0.5 ) ) ;
2018-12-12 08:18:24 +01:00
// Polygon editor
2023-04-05 22:04:00 +02:00
_initial_set ( " editors/polygon_editor/point_grab_radius " , has_touchscreen_ui ? 32 : 8 ) ;
2021-08-23 17:59:19 +02:00
_initial_set ( " editors/polygon_editor/show_previous_outline " , true ) ;
2017-10-28 15:40:55 +02:00
2018-12-12 08:18:24 +01:00
// Animation
_initial_set ( " editors/animation/autorename_animation_tracks " , true ) ;
_initial_set ( " editors/animation/confirm_insert_track " , true ) ;
2020-12-20 11:46:44 +01:00
_initial_set ( " editors/animation/default_create_bezier_tracks " , false ) ;
_initial_set ( " editors/animation/default_create_reset_tracks " , true ) ;
2018-12-12 08:18:24 +01:00
_initial_set ( " editors/animation/onion_layers_past_color " , Color ( 1 , 0 , 0 ) ) ;
_initial_set ( " editors/animation/onion_layers_future_color " , Color ( 0 , 1 , 0 ) ) ;
2021-01-25 15:37:05 +01:00
// Visual editors
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/visual_editors/minimap_opacity " , 0.85 , " 0.0,1.0,0.01 " )
2022-05-30 15:38:13 +02:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/visual_editors/lines_curvature " , 0.5 , " 0.0,1.0,0.01 " )
2022-08-03 11:38:29 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " editors/visual_editors/visual_shader/port_preview_size " , 160 , " 100,400,0.01 " )
2021-01-25 15:37:05 +01:00
2018-12-12 08:18:24 +01:00
/* Run */
// Window placement
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " run/window_placement/rect " , 1 , " Top Left,Centered,Custom Position,Force Maximized,Force Fullscreen " )
2023-01-04 23:00:02 +01:00
// Keep the enum values in sync with the `DisplayServer::SCREEN_` enum.
2023-03-21 12:08:46 +01:00
String screen_hints = " Same as Editor:-5,Previous Screen:-4,Next Screen:-3,Primary Screen:-2 " ; // Note: Main Window Screen:-1 is not used for the main window.
2020-03-03 14:36:29 +01:00
for ( int i = 0 ; i < DisplayServer : : get_singleton ( ) - > get_screen_count ( ) ; i + + ) {
2023-03-21 12:08:46 +01:00
screen_hints + = " ,Screen " + itos ( i + 1 ) + " : " + itos ( i ) ;
2017-10-28 15:40:55 +02:00
}
_initial_set ( " run/window_placement/rect_custom_position " , Vector2 ( ) ) ;
2023-01-04 23:00:02 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " run/window_placement/screen " , - 5 , screen_hints )
2017-10-28 15:40:55 +02:00
2018-12-12 08:18:24 +01:00
// Auto save
2017-10-28 15:40:55 +02:00
_initial_set ( " run/auto_save/save_before_running " , true ) ;
2018-12-12 08:18:24 +01:00
// Output
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " run/output/font_size " , 13 , " 8,48,1 " )
2017-10-28 15:40:55 +02:00
_initial_set ( " run/output/always_clear_output_on_play " , true ) ;
_initial_set ( " run/output/always_open_output_on_play " , true ) ;
_initial_set ( " run/output/always_close_output_on_stop " , false ) ;
2019-08-21 17:05:06 +02:00
/* Network */
// Debug
_initial_set ( " network/debug/remote_host " , " 127.0.0.1 " ) ; // Hints provided in setup_network
2021-08-16 07:30:24 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " network/debug/remote_port " , 6007 , " 1,65535,1 " )
2019-08-21 17:05:06 +02:00
// SSL
2022-09-07 08:25:47 +02:00
EDITOR_SETTING_USAGE ( Variant : : STRING , PROPERTY_HINT_GLOBAL_FILE , " network/tls/editor_tls_certificates " , _SYSTEM_CERTS_PATH , " *.crt,*.pem " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED ) ;
2019-08-21 17:05:06 +02:00
2022-03-06 21:39:19 +01:00
// Profiler
2022-05-28 01:03:32 +02:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " debugger/profiler_frame_history_size " , 3600 , " 60,10000,1 " )
2022-03-06 21:39:19 +01:00
2022-03-20 13:56:11 +01:00
// HTTP Proxy
_initial_set ( " network/http_proxy/host " , " " ) ;
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " network/http_proxy/port " , 8080 , " 1,65535,1 " )
2018-12-12 08:18:24 +01:00
/* Extra config */
2017-10-28 15:40:55 +02:00
2022-06-08 11:42:51 +02:00
// TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects.
2021-11-07 22:50:29 +01:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " project_manager/sorting_order " , 0 , " Last Edited,Name,Path " )
2023-01-31 17:23:59 +01:00
# if defined(WEB_ENABLED)
// Web platform only supports `gl_compatibility`.
2023-04-22 01:51:57 +02:00
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_ENUM , " project_manager/default_renderer " , " gl_compatibility " , " forward_plus,mobile,gl_compatibility " )
2023-01-31 17:23:59 +01:00
# elif defined(ANDROID_ENABLED)
// Use more suitable rendering method by default.
2023-04-22 01:51:57 +02:00
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_ENUM , " project_manager/default_renderer " , " mobile " , " forward_plus,mobile,gl_compatibility " )
2023-01-31 17:23:59 +01:00
# else
2023-04-22 01:51:57 +02:00
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_ENUM , " project_manager/default_renderer " , " forward_plus " , " forward_plus,mobile,gl_compatibility " )
2023-01-31 17:23:59 +01:00
# endif
2018-12-12 21:12:41 +01:00
2017-10-28 15:40:55 +02:00
if ( p_extra_config . is_valid ( ) ) {
if ( p_extra_config - > has_section ( " init_projects " ) & & p_extra_config - > has_section_key ( " init_projects " , " list " ) ) {
Vector < String > list = p_extra_config - > get_value ( " init_projects " , " list " ) ;
for ( int i = 0 ; i < list . size ( ) ; i + + ) {
2022-09-29 11:53:28 +02:00
String proj_name = list [ i ] . replace ( " / " , " :: " ) ;
set ( " projects/ " + proj_name , list [ i ] ) ;
2021-06-09 10:47:32 +02:00
}
}
2017-10-28 15:40:55 +02:00
if ( p_extra_config - > has_section ( " presets " ) ) {
List < String > keys ;
p_extra_config - > get_section_keys ( " presets " , & keys ) ;
2021-07-24 15:46:25 +02:00
for ( const String & key : keys ) {
2017-10-28 15:40:55 +02:00
Variant val = p_extra_config - > get_value ( " presets " , key ) ;
set ( key , val ) ;
2021-06-09 10:47:32 +02:00
}
}
}
2017-10-28 15:40:55 +02:00
}
2021-05-27 10:22:36 +02:00
void EditorSettings : : _load_godot2_text_editor_theme ( ) {
// Godot 2 is only a dark theme; it doesn't have a light theme counterpart.
2021-08-15 19:14:46 +02:00
_initial_set ( " text_editor/theme/highlighting/symbol_color " , Color ( 0.73 , 0.87 , 1.0 ) ) ;
_initial_set ( " text_editor/theme/highlighting/keyword_color " , Color ( 1.0 , 1.0 , 0.7 ) ) ;
_initial_set ( " text_editor/theme/highlighting/control_flow_keyword_color " , Color ( 1.0 , 0.85 , 0.7 ) ) ;
_initial_set ( " text_editor/theme/highlighting/base_type_color " , Color ( 0.64 , 1.0 , 0.83 ) ) ;
_initial_set ( " text_editor/theme/highlighting/engine_type_color " , Color ( 0.51 , 0.83 , 1.0 ) ) ;
_initial_set ( " text_editor/theme/highlighting/user_type_color " , Color ( 0.42 , 0.67 , 0.93 ) ) ;
_initial_set ( " text_editor/theme/highlighting/comment_color " , Color ( 0.4 , 0.4 , 0.4 ) ) ;
_initial_set ( " text_editor/theme/highlighting/string_color " , Color ( 0.94 , 0.43 , 0.75 ) ) ;
_initial_set ( " text_editor/theme/highlighting/background_color " , Color ( 0.13 , 0.12 , 0.15 ) ) ;
_initial_set ( " text_editor/theme/highlighting/completion_background_color " , Color ( 0.17 , 0.16 , 0.2 ) ) ;
_initial_set ( " text_editor/theme/highlighting/completion_selected_color " , Color ( 0.26 , 0.26 , 0.27 ) ) ;
2021-09-21 17:59:01 +02:00
_initial_set ( " text_editor/theme/highlighting/completion_existing_color " , Color ( 0.87 , 0.87 , 0.87 , 0.13 ) ) ;
2022-02-14 14:41:22 +01:00
_initial_set ( " text_editor/theme/highlighting/completion_scroll_color " , Color ( 1 , 1 , 1 , 0.29 ) ) ;
2022-06-27 11:27:17 +02:00
_initial_set ( " text_editor/theme/highlighting/completion_scroll_hovered_color " , Color ( 1 , 1 , 1 , 0.4 ) ) ;
2021-08-15 19:14:46 +02:00
_initial_set ( " text_editor/theme/highlighting/completion_font_color " , Color ( 0.67 , 0.67 , 0.67 ) ) ;
_initial_set ( " text_editor/theme/highlighting/text_color " , Color ( 0.67 , 0.67 , 0.67 ) ) ;
_initial_set ( " text_editor/theme/highlighting/line_number_color " , Color ( 0.67 , 0.67 , 0.67 , 0.4 ) ) ;
_initial_set ( " text_editor/theme/highlighting/safe_line_number_color " , Color ( 0.67 , 0.78 , 0.67 , 0.6 ) ) ;
_initial_set ( " text_editor/theme/highlighting/caret_color " , Color ( 0.67 , 0.67 , 0.67 ) ) ;
_initial_set ( " text_editor/theme/highlighting/caret_background_color " , Color ( 0 , 0 , 0 ) ) ;
2022-10-26 00:46:06 +02:00
_initial_set ( " text_editor/theme/highlighting/text_selected_color " , Color ( 0 , 0 , 0 , 0 ) ) ;
2021-08-15 19:14:46 +02:00
_initial_set ( " text_editor/theme/highlighting/selection_color " , Color ( 0.41 , 0.61 , 0.91 , 0.35 ) ) ;
_initial_set ( " text_editor/theme/highlighting/brace_mismatch_color " , Color ( 1 , 0.2 , 0.2 ) ) ;
_initial_set ( " text_editor/theme/highlighting/current_line_color " , Color ( 0.3 , 0.5 , 0.8 , 0.15 ) ) ;
_initial_set ( " text_editor/theme/highlighting/line_length_guideline_color " , Color ( 0.3 , 0.5 , 0.8 , 0.1 ) ) ;
_initial_set ( " text_editor/theme/highlighting/word_highlighted_color " , Color ( 0.8 , 0.9 , 0.9 , 0.15 ) ) ;
_initial_set ( " text_editor/theme/highlighting/number_color " , Color ( 0.92 , 0.58 , 0.2 ) ) ;
_initial_set ( " text_editor/theme/highlighting/function_color " , Color ( 0.4 , 0.64 , 0.81 ) ) ;
_initial_set ( " text_editor/theme/highlighting/member_variable_color " , Color ( 0.9 , 0.31 , 0.35 ) ) ;
_initial_set ( " text_editor/theme/highlighting/mark_color " , Color ( 1.0 , 0.4 , 0.4 , 0.4 ) ) ;
_initial_set ( " text_editor/theme/highlighting/bookmark_color " , Color ( 0.08 , 0.49 , 0.98 ) ) ;
_initial_set ( " text_editor/theme/highlighting/breakpoint_color " , Color ( 0.9 , 0.29 , 0.3 ) ) ;
_initial_set ( " text_editor/theme/highlighting/executing_line_color " , Color ( 0.98 , 0.89 , 0.27 ) ) ;
_initial_set ( " text_editor/theme/highlighting/code_folding_color " , Color ( 0.8 , 0.8 , 0.8 , 0.8 ) ) ;
_initial_set ( " text_editor/theme/highlighting/search_result_color " , Color ( 0.05 , 0.25 , 0.05 , 1 ) ) ;
_initial_set ( " text_editor/theme/highlighting/search_result_border_color " , Color ( 0.41 , 0.61 , 0.91 , 0.38 ) ) ;
2017-10-28 15:40:55 +02:00
}
bool EditorSettings : : _save_text_editor_theme ( String p_file ) {
String theme_section = " color_theme " ;
Ref < ConfigFile > cf = memnew ( ConfigFile ) ; // hex is better?
2018-06-10 14:06:24 +02:00
List < String > keys ;
2022-05-08 10:09:19 +02:00
for ( const KeyValue < String , VariantContainer > & E : props ) {
keys . push_back ( E . key ) ;
}
2018-06-10 14:06:24 +02:00
keys . sort ( ) ;
2021-07-16 05:45:57 +02:00
for ( const String & key : keys ) {
2021-08-15 19:14:46 +02:00
if ( key . begins_with ( " text_editor/theme/highlighting/ " ) & & key . find ( " color " ) > = 0 ) {
cf - > set_value ( theme_section , key . replace ( " text_editor/theme/highlighting/ " , " " ) , ( ( Color ) props [ key ] . variant ) . to_html ( ) ) ;
2018-06-10 14:06:24 +02:00
}
}
2018-04-12 23:26:15 +02:00
2017-10-28 15:40:55 +02:00
Error err = cf - > save ( p_file ) ;
2019-06-26 15:08:25 +02:00
return err = = OK ;
2017-10-28 15:40:55 +02:00
}
2019-05-23 17:18:24 +02:00
bool EditorSettings : : _is_default_text_editor_theme ( String p_theme_name ) {
2021-05-27 10:22:36 +02:00
return p_theme_name = = " default " | | p_theme_name = = " godot 2 " | | p_theme_name = = " custom " ;
2019-05-23 17:18:24 +02:00
}
2017-10-28 15:40:55 +02:00
// PUBLIC METHODS
EditorSettings * EditorSettings : : get_singleton ( ) {
return singleton . ptr ( ) ;
}
void EditorSettings : : create ( ) {
2021-06-09 10:47:32 +02:00
// IMPORTANT: create() *must* create a valid EditorSettings singleton,
// as the rest of the engine code will assume it. As such, it should never
// return (incl. via ERR_FAIL) without initializing the singleton member.
2020-05-14 16:41:43 +02:00
if ( singleton . ptr ( ) ) {
2021-06-09 10:47:32 +02:00
ERR_PRINT ( " Can't recreate EditorSettings as it already exists. " ) ;
return ;
2020-05-14 16:41:43 +02:00
}
2017-10-28 15:40:55 +02:00
2021-07-12 00:30:33 +02:00
GDREGISTER_CLASS ( EditorSettings ) ; // Otherwise it can't be unserialized.
2021-06-09 10:47:32 +02:00
String config_file_path ;
2017-10-28 15:40:55 +02:00
Ref < ConfigFile > extra_config = memnew ( ConfigFile ) ;
2021-06-09 10:47:32 +02:00
if ( ! EditorPaths : : get_singleton ( ) ) {
ERR_PRINT ( " Bug (please report): EditorPaths haven't been initialized, EditorSettings cannot be created properly. " ) ;
goto fail ;
}
2021-05-25 02:25:11 +02:00
if ( EditorPaths : : get_singleton ( ) - > is_self_contained ( ) ) {
Error err = extra_config - > load ( EditorPaths : : get_singleton ( ) - > get_self_contained_file ( ) ) ;
2019-08-07 12:54:30 +02:00
if ( err ! = OK ) {
2021-06-09 10:47:32 +02:00
ERR_PRINT ( " Can't load extra config from path: " + EditorPaths : : get_singleton ( ) - > get_self_contained_file ( ) ) ;
2019-08-07 12:54:30 +02:00
}
2017-10-28 15:40:55 +02:00
}
2021-05-25 02:25:11 +02:00
if ( EditorPaths : : get_singleton ( ) - > are_paths_valid ( ) ) {
2021-06-09 10:47:32 +02:00
// Validate editor config file.
2022-03-23 10:08:58 +01:00
Ref < DirAccess > dir = DirAccess : : open ( EditorPaths : : get_singleton ( ) - > get_config_dir ( ) ) ;
2017-11-20 07:40:06 +01:00
String config_file_name = " editor_settings- " + itos ( VERSION_MAJOR ) + " .tres " ;
2022-08-30 02:34:01 +02:00
config_file_path = EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . path_join ( config_file_name ) ;
2017-01-11 22:38:00 +01:00
if ( ! dir - > file_exists ( config_file_name ) ) {
2017-01-05 23:41:36 +01:00
goto fail ;
2014-02-10 02:10:30 +01:00
}
2017-11-17 15:50:18 +01:00
singleton = ResourceLoader : : load ( config_file_path , " EditorSettings " ) ;
2016-06-05 02:31:29 +02:00
2014-02-10 02:10:30 +01:00
if ( singleton . is_null ( ) ) {
2021-06-09 10:47:32 +02:00
ERR_PRINT ( " Could not load editor settings from path: " + config_file_path ) ;
2014-02-10 02:10:30 +01:00
goto fail ;
}
2016-06-12 02:16:14 +02:00
singleton - > save_changed_setting = true ;
2014-02-10 02:10:30 +01:00
2018-08-24 08:47:34 +02:00
print_verbose ( " EditorSettings: Load OK! " ) ;
2014-02-10 02:10:30 +01:00
2016-05-28 00:58:28 +02:00
singleton - > setup_language ( ) ;
2015-08-06 07:37:40 +02:00
singleton - > setup_network ( ) ;
2022-02-03 01:21:52 +01:00
singleton - > load_favorites_and_recent_dirs ( ) ;
2016-04-12 16:45:31 +02:00
singleton - > list_text_editor_themes ( ) ;
2014-02-10 02:10:30 +01:00
return ;
}
2017-10-28 15:40:55 +02:00
fail :
// patch init projects
2021-05-25 02:25:11 +02:00
String exe_path = OS : : get_singleton ( ) - > get_executable_path ( ) . get_base_dir ( ) ;
2017-10-28 15:40:55 +02:00
if ( extra_config - > has_section ( " init_projects " ) ) {
Vector < String > list = extra_config - > get_value ( " init_projects " , " list " ) ;
for ( int i = 0 ; i < list . size ( ) ; i + + ) {
2022-08-30 02:34:01 +02:00
list . write [ i ] = exe_path . path_join ( list [ i ] ) ;
2021-06-09 10:47:32 +02:00
}
2017-10-28 15:40:55 +02:00
extra_config - > set_value ( " init_projects " , " list " , list ) ;
2021-06-09 10:47:32 +02:00
}
2017-01-05 23:41:36 +01:00
2017-10-28 15:40:55 +02:00
singleton = Ref < EditorSettings > ( memnew ( EditorSettings ) ) ;
2022-06-03 01:33:42 +02:00
singleton - > set_path ( config_file_path , true ) ;
2017-10-28 15:40:55 +02:00
singleton - > save_changed_setting = true ;
singleton - > _load_defaults ( extra_config ) ;
singleton - > setup_language ( ) ;
singleton - > setup_network ( ) ;
singleton - > list_text_editor_themes ( ) ;
}
2017-01-05 23:41:36 +01:00
2017-10-28 15:40:55 +02:00
void EditorSettings : : setup_language ( ) {
2022-03-21 01:53:30 +01:00
TranslationServer : : get_singleton ( ) - > set_editor_pseudolocalization ( get ( " interface/editor/debug/enable_pseudolocalization " ) ) ;
2017-10-28 15:40:55 +02:00
String lang = get ( " interface/editor/editor_language " ) ;
2020-05-14 16:41:43 +02:00
if ( lang = = " en " ) {
2020-03-18 18:34:36 +01:00
return ; // Default, nothing to do.
2020-05-14 16:41:43 +02:00
}
2020-03-18 18:34:36 +01:00
// Load editor translation for configured/detected locale.
2021-12-15 16:01:06 +01:00
load_editor_translations ( lang ) ;
2022-12-27 03:58:01 +01:00
load_property_translations ( lang ) ;
2020-03-18 18:34:36 +01:00
// Load class reference translation.
2021-12-15 16:01:06 +01:00
load_doc_translations ( lang ) ;
2017-10-28 15:40:55 +02:00
}
2017-09-19 02:30:48 +02:00
2017-10-28 15:40:55 +02:00
void EditorSettings : : setup_network ( ) {
2021-05-06 02:48:18 +02:00
List < IPAddress > local_ip ;
2017-10-28 15:40:55 +02:00
IP : : get_singleton ( ) - > get_local_addresses ( & local_ip ) ;
String hint ;
String current = has_setting ( " network/debug/remote_host " ) ? get ( " network/debug/remote_host " ) : " " ;
2019-08-21 17:05:06 +02:00
String selected = " 127.0.0.1 " ;
2017-01-05 23:41:36 +01:00
2019-08-21 17:05:06 +02:00
// Check that current remote_host is a valid interface address and populate hints.
2021-07-24 15:46:25 +02:00
for ( const IPAddress & ip : local_ip ) {
2017-10-28 15:40:55 +02:00
// link-local IPv6 addresses don't work, skipping them
2021-07-16 05:45:57 +02:00
if ( String ( ip ) . begins_with ( " fe80:0:0:0: " ) ) { // fe80::/64
2017-10-28 15:40:55 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2019-03-31 16:57:23 +02:00
// Same goes for IPv4 link-local (APIPA) addresses.
2021-07-16 05:45:57 +02:00
if ( String ( ip ) . begins_with ( " 169.254. " ) ) { // 169.254.0.0/16
2019-03-31 16:57:23 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2019-08-21 17:05:06 +02:00
// Select current IP (found)
2020-05-14 16:41:43 +02:00
if ( ip = = current ) {
2019-08-21 17:05:06 +02:00
selected = ip ;
2020-05-14 16:41:43 +02:00
}
2021-12-09 10:42:46 +01:00
if ( ! hint . is_empty ( ) ) {
2017-10-28 15:40:55 +02:00
hint + = " , " ;
2020-05-14 16:41:43 +02:00
}
2017-10-28 15:40:55 +02:00
hint + = ip ;
}
2017-05-01 20:57:35 +02:00
2019-08-21 17:05:06 +02:00
// Add hints with valid IP addresses to remote_host property.
2017-10-28 15:40:55 +02:00
add_property_hint ( PropertyInfo ( Variant : : STRING , " network/debug/remote_host " , PROPERTY_HINT_ENUM , hint ) ) ;
2019-08-21 17:05:06 +02:00
// Fix potentially invalid remote_host due to network change.
set ( " network/debug/remote_host " , selected ) ;
2017-10-28 15:40:55 +02:00
}
2017-04-25 14:18:08 +02:00
2017-10-28 15:40:55 +02:00
void EditorSettings : : save ( ) {
//_THREAD_SAFE_METHOD_
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( ! singleton . ptr ( ) ) {
2017-10-28 15:40:55 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2022-06-03 01:33:42 +02:00
Error err = ResourceSaver : : save ( singleton ) ;
2016-08-16 18:25:42 +02:00
2017-10-28 15:40:55 +02:00
if ( err ! = OK ) {
2022-06-03 01:33:42 +02:00
ERR_PRINT ( " Error saving editor settings to " + singleton - > get_path ( ) ) ;
2018-08-24 08:47:34 +02:00
} else {
2021-10-15 14:34:11 +02:00
singleton - > changed_settings . clear ( ) ;
2018-08-24 08:47:34 +02:00
print_verbose ( " EditorSettings: Save OK! " ) ;
2017-10-28 15:40:55 +02:00
}
}
2014-02-10 02:10:30 +01:00
2022-08-05 03:41:48 +02:00
PackedStringArray EditorSettings : : get_changed_settings ( ) const {
PackedStringArray arr ;
2021-10-15 14:34:11 +02:00
for ( const String & setting : changed_settings ) {
arr . push_back ( setting ) ;
}
return arr ;
}
bool EditorSettings : : check_changed_settings_in_group ( const String & p_setting_prefix ) const {
for ( const String & setting : changed_settings ) {
if ( setting . begins_with ( p_setting_prefix ) ) {
return true ;
}
}
return false ;
}
void EditorSettings : : mark_setting_changed ( const String & p_setting ) {
changed_settings . insert ( p_setting ) ;
}
2017-10-28 15:40:55 +02:00
void EditorSettings : : destroy ( ) {
2020-05-14 16:41:43 +02:00
if ( ! singleton . ptr ( ) ) {
2017-10-28 15:40:55 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-10-28 15:40:55 +02:00
save ( ) ;
singleton = Ref < EditorSettings > ( ) ;
}
2014-02-10 02:10:30 +01:00
2017-10-28 15:40:55 +02:00
void EditorSettings : : set_optimize_save ( bool p_optimize ) {
optimize_save = p_optimize ;
}
2016-05-27 19:18:40 +02:00
2017-10-28 15:40:55 +02:00
// Properties
2016-02-22 00:15:47 +01:00
2017-10-28 15:40:55 +02:00
void EditorSettings : : set_setting ( const String & p_setting , const Variant & p_value ) {
_THREAD_SAFE_METHOD_
set ( p_setting , p_value ) ;
}
2016-02-27 16:11:40 +01:00
2017-10-28 15:40:55 +02:00
Variant EditorSettings : : get_setting ( const String & p_setting ) const {
_THREAD_SAFE_METHOD_
return get ( p_setting ) ;
}
2016-02-27 16:11:40 +01:00
2017-10-31 15:24:35 +01:00
bool EditorSettings : : has_setting ( const String & p_setting ) const {
2017-10-28 15:40:55 +02:00
_THREAD_SAFE_METHOD_
2016-02-27 16:11:40 +01:00
2017-10-31 15:24:35 +01:00
return props . has ( p_setting ) ;
2017-10-28 15:40:55 +02:00
}
2016-02-27 16:11:40 +01:00
2017-10-31 15:24:35 +01:00
void EditorSettings : : erase ( const String & p_setting ) {
2017-10-28 15:40:55 +02:00
_THREAD_SAFE_METHOD_
2017-10-31 15:24:35 +01:00
props . erase ( p_setting ) ;
2016-04-12 16:45:31 +02:00
}
2017-10-31 15:24:35 +01:00
void EditorSettings : : raise_order ( const String & p_setting ) {
2017-10-28 15:40:55 +02:00
_THREAD_SAFE_METHOD_
2017-10-31 15:24:35 +01:00
ERR_FAIL_COND ( ! props . has ( p_setting ) ) ;
props [ p_setting ] . order = + + last_order ;
2014-02-10 02:10:30 +01:00
}
2018-07-19 23:58:15 +02:00
void EditorSettings : : set_restart_if_changed ( const StringName & p_setting , bool p_restart ) {
_THREAD_SAFE_METHOD_
2020-05-14 16:41:43 +02:00
if ( ! props . has ( p_setting ) ) {
2018-07-19 23:58:15 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2018-07-19 23:58:15 +02:00
props [ p_setting ] . restart_if_changed = p_restart ;
}
2018-01-09 16:52:46 +01:00
void EditorSettings : : set_initial_value ( const StringName & p_setting , const Variant & p_value , bool p_update_current ) {
2017-11-30 04:11:53 +01:00
_THREAD_SAFE_METHOD_
2020-05-14 16:41:43 +02:00
if ( ! props . has ( p_setting ) ) {
2017-11-17 21:22:27 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2018-01-07 20:39:38 +01:00
props [ p_setting ] . initial = p_value ;
props [ p_setting ] . has_default_value = true ;
2018-01-09 16:52:46 +01:00
if ( p_update_current ) {
2018-01-07 20:39:38 +01:00
set ( p_setting , p_value ) ;
}
2017-10-28 15:40:55 +02:00
}
2014-02-10 02:10:30 +01:00
2018-07-19 23:58:15 +02:00
Variant _EDITOR_DEF ( const String & p_setting , const Variant & p_default , bool p_restart_if_changed ) {
2021-10-21 22:21:41 +02:00
ERR_FAIL_NULL_V_MSG ( EditorSettings : : get_singleton ( ) , p_default , " EditorSettings not instantiated yet. " ) ;
2017-10-28 23:25:28 +02:00
Variant ret = p_default ;
2018-07-19 23:58:15 +02:00
if ( EditorSettings : : get_singleton ( ) - > has_setting ( p_setting ) ) {
2022-10-18 16:43:37 +02:00
ret = EDITOR_GET ( p_setting ) ;
2018-07-19 23:58:15 +02:00
} else {
2017-11-30 04:11:53 +01:00
EditorSettings : : get_singleton ( ) - > set_manually ( p_setting , p_default ) ;
2018-07-19 23:58:15 +02:00
EditorSettings : : get_singleton ( ) - > set_restart_if_changed ( p_setting , p_restart_if_changed ) ;
}
2017-11-30 04:11:53 +01:00
2018-07-19 23:58:15 +02:00
if ( ! EditorSettings : : get_singleton ( ) - > has_default_value ( p_setting ) ) {
2017-11-20 18:34:13 +01:00
EditorSettings : : get_singleton ( ) - > set_initial_value ( p_setting , p_default ) ;
2018-07-19 23:58:15 +02:00
}
2014-02-10 02:10:30 +01:00
2017-10-28 23:25:28 +02:00
return ret ;
2017-10-28 15:40:55 +02:00
}
2014-02-10 02:10:30 +01:00
2017-10-31 15:24:35 +01:00
Variant _EDITOR_GET ( const String & p_setting ) {
2021-10-21 22:21:41 +02:00
ERR_FAIL_COND_V ( ! EditorSettings : : get_singleton ( ) | | ! EditorSettings : : get_singleton ( ) - > has_setting ( p_setting ) , Variant ( ) ) ;
2017-10-31 15:24:35 +01:00
return EditorSettings : : get_singleton ( ) - > get ( p_setting ) ;
2014-02-10 02:10:30 +01:00
}
2022-08-12 20:43:14 +02:00
bool EditorSettings : : _property_can_revert ( const StringName & p_name ) const {
if ( ! props . has ( p_name ) ) {
2017-10-28 15:40:55 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2016-08-16 22:10:53 +02:00
2022-08-12 20:43:14 +02:00
if ( ! props [ p_name ] . has_default_value ) {
2017-11-30 04:11:53 +01:00
return false ;
2020-05-14 16:41:43 +02:00
}
2017-11-30 04:11:53 +01:00
2022-08-12 20:43:14 +02:00
return props [ p_name ] . initial ! = props [ p_name ] . variant ;
2017-10-28 15:40:55 +02:00
}
2016-08-16 22:10:53 +02:00
2022-08-12 20:43:14 +02:00
bool EditorSettings : : _property_get_revert ( const StringName & p_name , Variant & r_property ) const {
if ( ! props . has ( p_name ) | | ! props [ p_name ] . has_default_value ) {
return false ;
2020-05-14 16:41:43 +02:00
}
2017-10-28 15:40:55 +02:00
2022-08-12 20:43:14 +02:00
r_property = props [ p_name ] . initial ;
return true ;
2016-08-16 22:10:53 +02:00
}
2014-02-10 02:10:30 +01:00
void EditorSettings : : add_property_hint ( const PropertyInfo & p_hint ) {
_THREAD_SAFE_METHOD_
hints [ p_hint . name ] = p_hint ;
}
Add initial support for the XDG Base Directory spec
Spec version 0.7 from https://standards.freedesktop.org/basedir-spec/basedir-spec-0.7.html
(latest as of this commit).
Three virtual methods are added to OS for the various XDG paths we will use:
- OS::get_data_path gives XDG_DATA_HOME, or if missing:
~/.local/share on X11, ~/Library/Application Support/ on macOS and %APPDATA% on Windows
- OS::get_config_path gives XDG_CONFIG_HOME, or if missing:
~/.config on X11, ~/Library/Application Support/ on macOS and %APPDATA% on Windows
- OS::get_cache_path gives XDG_CACHE_HOME, or if missing:
~/.cache on X11, ~/Library/Caches on macOS and %APPDATA% on Windows
So for Windows there are no changes, for Linux we follow the full split spec
and for macOS stuff will move from ~/.godot to ~/Library/Application Support/Godot.
Support for system-wide installation of templates on Unix was removed for now,
as it's a bit hackish and I don't think anyone uses it.
user:// will still be OS::get_data_path() + "/godot/app_userdata/$name" by
default, but when using the application/config/use_shared_user_dir option
it will now use XDG_DATA_HOME/$name, e.g. ~/.local/share/MyGame.
For now everything still goes in EditorSettings::get_settings_dir(), but
this will be changed in a later commit to make use of the new splitting
where relevant.
Part of #3513.
2017-11-17 17:11:41 +01:00
// Metadata
2017-10-28 15:40:55 +02:00
void EditorSettings : : set_project_metadata ( const String & p_section , const String & p_key , Variant p_data ) {
Ref < ConfigFile > cf = memnew ( ConfigFile ) ;
2022-08-30 02:34:01 +02:00
String path = EditorPaths : : get_singleton ( ) - > get_project_settings_dir ( ) . path_join ( " project_metadata.cfg " ) ;
2019-08-07 12:54:30 +02:00
Error err ;
err = cf - > load ( path ) ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( err ! = OK & & err ! = ERR_FILE_NOT_FOUND , " Cannot load editor settings from file ' " + path + " '. " ) ;
2017-10-28 15:40:55 +02:00
cf - > set_value ( p_section , p_key , p_data ) ;
2019-08-07 12:54:30 +02:00
err = cf - > save ( path ) ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( err ! = OK , " Cannot save editor settings to file ' " + path + " '. " ) ;
2017-10-28 15:40:55 +02:00
}
2018-05-16 17:23:20 +02:00
Variant EditorSettings : : get_project_metadata ( const String & p_section , const String & p_key , Variant p_default ) const {
2017-10-28 15:40:55 +02:00
Ref < ConfigFile > cf = memnew ( ConfigFile ) ;
2022-08-30 02:34:01 +02:00
String path = EditorPaths : : get_singleton ( ) - > get_project_settings_dir ( ) . path_join ( " project_metadata.cfg " ) ;
2017-10-28 15:40:55 +02:00
Error err = cf - > load ( path ) ;
if ( err ! = OK ) {
return p_default ;
}
return cf - > get_value ( p_section , p_key , p_default ) ;
}
2018-09-18 14:02:59 +02:00
void EditorSettings : : set_favorites ( const Vector < String > & p_favorites ) {
favorites = p_favorites ;
2022-02-03 01:21:52 +01:00
String favorites_file ;
if ( Engine : : get_singleton ( ) - > is_project_manager_hint ( ) ) {
2022-08-30 02:34:01 +02:00
favorites_file = EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . path_join ( " favorite_dirs " ) ;
2022-02-03 01:21:52 +01:00
} else {
2022-08-30 02:34:01 +02:00
favorites_file = EditorPaths : : get_singleton ( ) - > get_project_settings_dir ( ) . path_join ( " favorites " ) ;
2022-02-03 01:21:52 +01:00
}
2022-03-23 10:08:58 +01:00
Ref < FileAccess > f = FileAccess : : open ( favorites_file , FileAccess : : WRITE ) ;
if ( f . is_valid ( ) ) {
2020-05-14 16:41:43 +02:00
for ( int i = 0 ; i < favorites . size ( ) ; i + + ) {
2018-09-18 14:02:59 +02:00
f - > store_line ( favorites [ i ] ) ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
}
}
2018-09-18 14:02:59 +02:00
Vector < String > EditorSettings : : get_favorites ( ) const {
return favorites ;
2015-06-06 14:44:38 +02:00
}
2017-08-12 18:52:50 +02:00
void EditorSettings : : set_recent_dirs ( const Vector < String > & p_recent_dirs ) {
recent_dirs = p_recent_dirs ;
2022-02-03 01:21:52 +01:00
String recent_dirs_file ;
if ( Engine : : get_singleton ( ) - > is_project_manager_hint ( ) ) {
2022-08-30 02:34:01 +02:00
recent_dirs_file = EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . path_join ( " recent_dirs " ) ;
2022-02-03 01:21:52 +01:00
} else {
2022-08-30 02:34:01 +02:00
recent_dirs_file = EditorPaths : : get_singleton ( ) - > get_project_settings_dir ( ) . path_join ( " recent_dirs " ) ;
2022-02-03 01:21:52 +01:00
}
2022-03-23 10:08:58 +01:00
Ref < FileAccess > f = FileAccess : : open ( recent_dirs_file , FileAccess : : WRITE ) ;
if ( f . is_valid ( ) ) {
2020-05-14 16:41:43 +02:00
for ( int i = 0 ; i < recent_dirs . size ( ) ; i + + ) {
2015-06-06 14:44:38 +02:00
f - > store_line ( recent_dirs [ i ] ) ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
}
}
Vector < String > EditorSettings : : get_recent_dirs ( ) const {
return recent_dirs ;
}
2022-02-03 01:21:52 +01:00
void EditorSettings : : load_favorites_and_recent_dirs ( ) {
String favorites_file ;
String recent_dirs_file ;
if ( Engine : : get_singleton ( ) - > is_project_manager_hint ( ) ) {
2022-08-30 02:34:01 +02:00
favorites_file = EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . path_join ( " favorite_dirs " ) ;
recent_dirs_file = EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . path_join ( " recent_dirs " ) ;
2022-02-03 01:21:52 +01:00
} else {
2022-08-30 02:34:01 +02:00
favorites_file = EditorPaths : : get_singleton ( ) - > get_project_settings_dir ( ) . path_join ( " favorites " ) ;
recent_dirs_file = EditorPaths : : get_singleton ( ) - > get_project_settings_dir ( ) . path_join ( " recent_dirs " ) ;
2022-02-03 01:21:52 +01:00
}
2022-03-23 10:08:58 +01:00
Ref < FileAccess > f = FileAccess : : open ( favorites_file , FileAccess : : READ ) ;
if ( f . is_valid ( ) ) {
2015-06-06 14:44:38 +02:00
String line = f - > get_line ( ) . strip_edges ( ) ;
2021-12-09 10:42:46 +01:00
while ( ! line . is_empty ( ) ) {
2018-09-18 14:02:59 +02:00
favorites . push_back ( line ) ;
2015-06-06 14:44:38 +02:00
line = f - > get_line ( ) . strip_edges ( ) ;
}
}
2022-02-03 01:21:52 +01:00
f = FileAccess : : open ( recent_dirs_file , FileAccess : : READ ) ;
2022-03-23 10:08:58 +01:00
if ( f . is_valid ( ) ) {
2015-06-06 14:44:38 +02:00
String line = f - > get_line ( ) . strip_edges ( ) ;
2021-12-09 10:42:46 +01:00
while ( ! line . is_empty ( ) ) {
2015-06-06 14:44:38 +02:00
recent_dirs . push_back ( line ) ;
line = f - > get_line ( ) . strip_edges ( ) ;
}
}
}
2018-06-10 16:30:49 +02:00
bool EditorSettings : : is_dark_theme ( ) {
int AUTO_COLOR = 0 ;
int LIGHT_COLOR = 2 ;
Color base_color = get ( " interface/theme/base_color " ) ;
int icon_font_color_setting = get ( " interface/theme/icon_and_font_color " ) ;
2021-12-16 06:59:04 +01:00
return ( icon_font_color_setting = = AUTO_COLOR & & base_color . get_luminance ( ) < 0.5 ) | | icon_font_color_setting = = LIGHT_COLOR ;
2018-06-10 16:30:49 +02:00
}
2016-04-12 16:45:31 +02:00
void EditorSettings : : list_text_editor_themes ( ) {
2021-05-27 10:22:36 +02:00
String themes = " Default,Godot 2,Custom " ;
2018-09-22 10:02:20 +02:00
2022-07-29 02:36:26 +02:00
Ref < DirAccess > d = DirAccess : : open ( EditorPaths : : get_singleton ( ) - > get_text_editor_themes_dir ( ) ) ;
2022-03-23 10:08:58 +01:00
if ( d . is_valid ( ) ) {
2018-09-22 10:02:20 +02:00
List < String > custom_themes ;
2016-04-12 16:45:31 +02:00
d - > list_dir_begin ( ) ;
String file = d - > get_next ( ) ;
2021-12-09 10:42:46 +01:00
while ( ! file . is_empty ( ) ) {
2019-05-23 17:18:24 +02:00
if ( file . get_extension ( ) = = " tet " & & ! _is_default_text_editor_theme ( file . get_basename ( ) . to_lower ( ) ) ) {
2018-09-22 10:02:20 +02:00
custom_themes . push_back ( file . get_basename ( ) ) ;
2016-04-12 16:45:31 +02:00
}
file = d - > get_next ( ) ;
}
d - > list_dir_end ( ) ;
2018-09-22 10:02:20 +02:00
custom_themes . sort ( ) ;
2021-07-24 15:46:25 +02:00
for ( const String & E : custom_themes ) {
2021-07-16 05:45:57 +02:00
themes + = " , " + E ;
2018-09-22 10:02:20 +02:00
}
2016-04-12 16:45:31 +02:00
}
2017-01-05 23:41:36 +01:00
add_property_hint ( PropertyInfo ( Variant : : STRING , " text_editor/theme/color_theme " , PROPERTY_HINT_ENUM , themes ) ) ;
2016-04-12 16:45:31 +02:00
}
void EditorSettings : : load_text_editor_theme ( ) {
2019-05-23 17:18:24 +02:00
String p_file = get ( " text_editor/theme/color_theme " ) ;
if ( _is_default_text_editor_theme ( p_file . get_file ( ) . to_lower ( ) ) ) {
2021-05-27 10:22:36 +02:00
if ( p_file = = " Godot 2 " ) {
_load_godot2_text_editor_theme ( ) ;
2018-01-06 12:40:43 +01:00
}
return ; // sorry for "Settings changed" console spam
2016-04-12 16:45:31 +02:00
}
2022-08-30 02:34:01 +02:00
String theme_path = EditorPaths : : get_singleton ( ) - > get_text_editor_themes_dir ( ) . path_join ( p_file + " .tet " ) ;
2016-04-12 16:45:31 +02:00
Ref < ConfigFile > cf = memnew ( ConfigFile ) ;
Error err = cf - > load ( theme_path ) ;
if ( err ! = OK ) {
return ;
}
List < String > keys ;
cf - > get_section_keys ( " color_theme " , & keys ) ;
2021-07-24 15:46:25 +02:00
for ( const String & key : keys ) {
2016-04-12 16:45:31 +02:00
String val = cf - > get_value ( " color_theme " , key ) ;
// don't load if it's not already there!
2021-08-15 19:14:46 +02:00
if ( has_setting ( " text_editor/theme/highlighting/ " + key ) ) {
2016-04-12 16:45:31 +02:00
// make sure it is actually a color
if ( val . is_valid_html_color ( ) & & key . find ( " color " ) > = 0 ) {
2021-08-15 19:14:46 +02:00
props [ " text_editor/theme/highlighting/ " + key ] . variant = Color : : html ( val ) ; // change manually to prevent "Settings changed" console spam
2016-04-12 16:45:31 +02:00
}
}
}
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " settings_changed " ) ) ;
2016-04-12 16:45:31 +02:00
// if it doesn't load just use what is currently loaded
}
bool EditorSettings : : import_text_editor_theme ( String p_file ) {
if ( ! p_file . ends_with ( " .tet " ) ) {
return false ;
} else {
if ( p_file . get_file ( ) . to_lower ( ) = = " default.tet " ) {
return false ;
}
2022-07-29 02:36:26 +02:00
Ref < DirAccess > d = DirAccess : : open ( EditorPaths : : get_singleton ( ) - > get_text_editor_themes_dir ( ) ) ;
2022-03-23 10:08:58 +01:00
if ( d . is_valid ( ) ) {
2022-08-30 02:34:01 +02:00
d - > copy ( p_file , EditorPaths : : get_singleton ( ) - > get_text_editor_themes_dir ( ) . path_join ( p_file . get_file ( ) ) ) ;
2016-04-12 16:45:31 +02:00
return true ;
}
}
return false ;
}
bool EditorSettings : : save_text_editor_theme ( ) {
2017-01-05 23:41:36 +01:00
String p_file = get ( " text_editor/theme/color_theme " ) ;
2016-04-12 16:45:31 +02:00
2019-05-23 17:18:24 +02:00
if ( _is_default_text_editor_theme ( p_file . get_file ( ) . to_lower ( ) ) ) {
2016-04-12 16:45:31 +02:00
return false ;
}
2022-08-30 02:34:01 +02:00
String theme_path = EditorPaths : : get_singleton ( ) - > get_text_editor_themes_dir ( ) . path_join ( p_file + " .tet " ) ;
2016-04-12 16:45:31 +02:00
return _save_text_editor_theme ( theme_path ) ;
}
bool EditorSettings : : save_text_editor_theme_as ( String p_file ) {
if ( ! p_file . ends_with ( " .tet " ) ) {
p_file + = " .tet " ;
}
2019-05-23 17:18:24 +02:00
if ( _is_default_text_editor_theme ( p_file . get_file ( ) . to_lower ( ) . trim_suffix ( " .tet " ) ) ) {
2016-04-12 16:45:31 +02:00
return false ;
}
if ( _save_text_editor_theme ( p_file ) ) {
// switch to theme is saved in the theme directory
list_text_editor_themes ( ) ;
String theme_name = p_file . substr ( 0 , p_file . length ( ) - 4 ) . get_file ( ) ;
2022-07-29 02:36:26 +02:00
if ( p_file . get_base_dir ( ) = = EditorPaths : : get_singleton ( ) - > get_text_editor_themes_dir ( ) ) {
2017-09-25 05:26:41 +02:00
_initial_set ( " text_editor/theme/color_theme " , theme_name ) ;
2016-04-12 16:45:31 +02:00
load_text_editor_theme ( ) ;
}
return true ;
}
return false ;
}
2019-05-23 17:18:24 +02:00
bool EditorSettings : : is_default_text_editor_theme ( ) {
String p_file = get ( " text_editor/theme/color_theme " ) ;
return _is_default_text_editor_theme ( p_file . get_file ( ) . to_lower ( ) ) ;
}
2019-08-22 17:59:43 +02:00
Vector < String > EditorSettings : : get_script_templates ( const String & p_extension , const String & p_custom_path ) {
2017-06-13 22:03:08 +02:00
Vector < String > templates ;
2022-07-29 02:36:26 +02:00
String template_dir = EditorPaths : : get_singleton ( ) - > get_script_templates_dir ( ) ;
2020-12-15 13:04:21 +01:00
if ( ! p_custom_path . is_empty ( ) ) {
2019-08-22 17:59:43 +02:00
template_dir = p_custom_path ;
}
2022-03-23 10:08:58 +01:00
Ref < DirAccess > d = DirAccess : : open ( template_dir ) ;
if ( d . is_valid ( ) ) {
2017-06-13 22:03:08 +02:00
d - > list_dir_begin ( ) ;
String file = d - > get_next ( ) ;
2021-12-09 10:42:46 +01:00
while ( ! file . is_empty ( ) ) {
2017-06-13 22:03:08 +02:00
if ( file . get_extension ( ) = = p_extension ) {
templates . push_back ( file . get_basename ( ) ) ;
}
file = d - > get_next ( ) ;
}
d - > list_dir_end ( ) ;
}
return templates ;
}
2017-11-17 21:48:24 +01:00
String EditorSettings : : get_editor_layouts_config ( ) const {
2022-08-30 02:34:01 +02:00
return EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . path_join ( " editor_layouts.cfg " ) ;
2017-11-17 21:48:24 +01:00
}
2021-06-16 14:36:09 +02:00
float EditorSettings : : get_auto_display_scale ( ) const {
2022-07-20 08:28:22 +02:00
# if defined(MACOS_ENABLED) || defined(ANDROID_ENABLED)
2021-06-16 14:36:09 +02:00
return DisplayServer : : get_singleton ( ) - > screen_get_max_scale ( ) ;
# else
const int screen = DisplayServer : : get_singleton ( ) - > window_get_current_screen ( ) ;
2022-02-21 09:17:28 +01:00
if ( DisplayServer : : get_singleton ( ) - > screen_get_size ( screen ) = = Vector2i ( ) ) {
// Invalid screen size, skip.
return 1.0 ;
}
Fix various typos with codespell
Found via `codespell -q 3 -S ./thirdparty,*.po,./DONORS.md -L ackward,ang,ans,ba,beng,cas,childs,childrens,dof,doubleclick,fave,findn,hist,inout,leapyear,lod,nd,numer,ois,ony,paket,seeked,sinc,switchs,te,uint`
2021-07-07 17:17:32 +02:00
// Use the smallest dimension to use a correct display scale on portrait displays.
2021-06-16 14:36:09 +02:00
const int smallest_dimension = MIN ( DisplayServer : : get_singleton ( ) - > screen_get_size ( screen ) . x , DisplayServer : : get_singleton ( ) - > screen_get_size ( screen ) . y ) ;
if ( DisplayServer : : get_singleton ( ) - > screen_get_dpi ( screen ) > = 192 & & smallest_dimension > = 1400 ) {
// hiDPI display.
return 2.0 ;
} else if ( smallest_dimension > = 1700 ) {
// Likely a hiDPI display, but we aren't certain due to the returned DPI.
// Use an intermediate scale to handle this situation.
return 1.5 ;
} else if ( smallest_dimension < = 800 ) {
// Small loDPI display. Use a smaller display scale so that editor elements fit more easily.
// Icons won't look great, but this is better than having editor elements overflow from its window.
return 0.75 ;
}
return 1.0 ;
# endif
}
2017-10-28 15:40:55 +02:00
// Shortcuts
2014-02-10 02:10:30 +01:00
2023-02-21 07:08:53 +01:00
void EditorSettings : : _add_shortcut_default ( const String & p_name , const Ref < Shortcut > & p_shortcut ) {
shortcuts [ p_name ] = p_shortcut ;
}
2022-04-05 12:40:26 +02:00
void EditorSettings : : add_shortcut ( const String & p_name , const Ref < Shortcut > & p_shortcut ) {
2016-06-05 02:31:29 +02:00
shortcuts [ p_name ] = p_shortcut ;
2023-02-21 07:08:53 +01:00
shortcuts [ p_name ] - > set_meta ( " customized " , true ) ;
2016-06-05 02:31:29 +02:00
}
2017-05-20 17:38:03 +02:00
bool EditorSettings : : is_shortcut ( const String & p_name , const Ref < InputEvent > & p_event ) const {
2022-05-13 15:04:37 +02:00
HashMap < String , Ref < Shortcut > > : : ConstIterator E = shortcuts . find ( p_name ) ;
2019-08-15 04:57:49 +02:00
ERR_FAIL_COND_V_MSG ( ! E , false , " Unknown Shortcut: " + p_name + " . " ) ;
2016-06-05 02:31:29 +02:00
2022-05-13 15:04:37 +02:00
return E - > value - > matches_event ( p_event ) ;
2016-06-05 02:31:29 +02:00
}
2020-09-09 21:53:24 +02:00
Ref < Shortcut > EditorSettings : : get_shortcut ( const String & p_name ) const {
2022-05-13 15:04:37 +02:00
HashMap < String , Ref < Shortcut > > : : ConstIterator SC = shortcuts . find ( p_name ) ;
2020-12-07 12:31:51 +01:00
if ( SC ) {
2022-05-13 15:04:37 +02:00
return SC - > value ;
2020-12-07 12:31:51 +01:00
}
// If no shortcut with the provided name is found in the list, check the built-in shortcuts.
// Use the first item in the action list for the shortcut event, since a shortcut can only have 1 linked event.
Ref < Shortcut > sc ;
2022-05-13 15:04:37 +02:00
HashMap < String , List < Ref < InputEvent > > > : : ConstIterator builtin_override = builtin_action_overrides . find ( p_name ) ;
2020-12-07 12:31:51 +01:00
if ( builtin_override ) {
2021-06-18 00:03:09 +02:00
sc . instantiate ( ) ;
2022-05-13 15:04:37 +02:00
sc - > set_events_list ( & builtin_override - > value ) ;
2020-12-07 12:31:51 +01:00
sc - > set_name ( InputMap : : get_singleton ( ) - > get_builtin_display_name ( p_name ) ) ;
}
// If there was no override, check the default builtins to see if it has an InputEvent for the provided name.
if ( sc . is_null ( ) ) {
2022-05-13 15:04:37 +02:00
HashMap < String , List < Ref < InputEvent > > > : : ConstIterator builtin_default = InputMap : : get_singleton ( ) - > get_builtins_with_feature_overrides_applied ( ) . find ( p_name ) ;
2020-12-07 12:31:51 +01:00
if ( builtin_default ) {
2021-06-18 00:03:09 +02:00
sc . instantiate ( ) ;
2022-05-08 10:09:19 +02:00
sc - > set_events_list ( & builtin_default - > value ) ;
2020-12-07 12:31:51 +01:00
sc - > set_name ( InputMap : : get_singleton ( ) - > get_builtin_display_name ( p_name ) ) ;
}
}
if ( sc . is_valid ( ) ) {
// Add the shortcut to the list.
shortcuts [ p_name ] = sc ;
return sc ;
2020-05-14 16:41:43 +02:00
}
2016-06-05 02:31:29 +02:00
2020-12-07 12:31:51 +01:00
return Ref < Shortcut > ( ) ;
2016-06-05 02:31:29 +02:00
}
void EditorSettings : : get_shortcut_list ( List < String > * r_shortcuts ) {
2021-08-09 22:13:42 +02:00
for ( const KeyValue < String , Ref < Shortcut > > & E : shortcuts ) {
r_shortcuts - > push_back ( E . key ) ;
2016-06-05 02:31:29 +02:00
}
}
2020-09-09 21:53:24 +02:00
Ref < Shortcut > ED_GET_SHORTCUT ( const String & p_path ) {
2021-10-21 22:21:41 +02:00
ERR_FAIL_NULL_V_MSG ( EditorSettings : : get_singleton ( ) , nullptr , " EditorSettings not instantiated yet. " ) ;
2019-06-01 15:42:22 +02:00
2020-09-09 21:53:24 +02:00
Ref < Shortcut > sc = EditorSettings : : get_singleton ( ) - > get_shortcut ( p_path ) ;
2019-08-15 04:57:49 +02:00
ERR_FAIL_COND_V_MSG ( ! sc . is_valid ( ) , sc , " Used ED_GET_SHORTCUT with invalid shortcut: " + p_path + " . " ) ;
2017-10-28 15:40:55 +02:00
return sc ;
2016-07-04 00:13:45 +02:00
}
2016-06-05 02:31:29 +02:00
2023-02-20 23:11:57 +01:00
void ED_SHORTCUT_OVERRIDE ( const String & p_path , const String & p_feature , Key p_keycode , bool p_physical ) {
2021-10-21 22:21:41 +02:00
ERR_FAIL_NULL_MSG ( EditorSettings : : get_singleton ( ) , " EditorSettings not instantiated yet. " ) ;
2021-08-08 05:52:00 +02:00
Ref < Shortcut > sc = EditorSettings : : get_singleton ( ) - > get_shortcut ( p_path ) ;
ERR_FAIL_COND_MSG ( ! sc . is_valid ( ) , " Used ED_SHORTCUT_OVERRIDE with invalid shortcut: " + p_path + " . " ) ;
2021-06-21 03:34:50 +02:00
PackedInt32Array arr ;
2021-08-13 23:31:57 +02:00
arr . push_back ( ( int32_t ) p_keycode ) ;
2021-06-21 03:34:50 +02:00
2023-02-20 23:11:57 +01:00
ED_SHORTCUT_OVERRIDE_ARRAY ( p_path , p_feature , arr , p_physical ) ;
2021-06-21 03:34:50 +02:00
}
2023-02-20 23:11:57 +01:00
void ED_SHORTCUT_OVERRIDE_ARRAY ( const String & p_path , const String & p_feature , const PackedInt32Array & p_keycodes , bool p_physical ) {
2021-10-21 22:21:41 +02:00
ERR_FAIL_NULL_MSG ( EditorSettings : : get_singleton ( ) , " EditorSettings not instantiated yet. " ) ;
2021-06-21 03:34:50 +02:00
Ref < Shortcut > sc = EditorSettings : : get_singleton ( ) - > get_shortcut ( p_path ) ;
ERR_FAIL_COND_MSG ( ! sc . is_valid ( ) , " Used ED_SHORTCUT_OVERRIDE_ARRAY with invalid shortcut: " + p_path + " . " ) ;
2021-08-08 05:52:00 +02:00
// Only add the override if the OS supports the provided feature.
2021-06-21 03:34:50 +02:00
if ( ! OS : : get_singleton ( ) - > has_feature ( p_feature ) ) {
2022-11-14 15:27:26 +01:00
if ( ! ( p_feature = = " macos " & & ( OS : : get_singleton ( ) - > has_feature ( " web_macos " ) | | OS : : get_singleton ( ) - > has_feature ( " web_ios " ) ) ) ) {
return ;
}
2021-06-21 03:34:50 +02:00
}
Array events ;
for ( int i = 0 ; i < p_keycodes . size ( ) ; i + + ) {
Key keycode = ( Key ) p_keycodes [ i ] ;
2022-11-14 15:27:26 +01:00
if ( OS : : get_singleton ( ) - > has_feature ( " macos " ) | | OS : : get_singleton ( ) - > has_feature ( " web_macos " ) | | OS : : get_singleton ( ) - > has_feature ( " web_ios " ) ) {
// Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
if ( keycode = = Key : : KEY_DELETE ) {
keycode = KeyModifierMask : : META | Key : : BACKSPACE ;
}
2021-08-08 05:52:00 +02:00
}
2022-09-02 11:37:48 +02:00
2021-06-21 03:34:50 +02:00
Ref < InputEventKey > ie ;
2021-08-13 23:31:57 +02:00
if ( keycode ! = Key : : NONE ) {
2023-02-20 23:11:57 +01:00
ie = InputEventKey : : create_reference ( keycode , p_physical ) ;
2021-06-21 03:34:50 +02:00
events . push_back ( ie ) ;
}
2021-08-08 05:52:00 +02:00
}
2021-06-21 03:34:50 +02:00
2023-02-21 07:08:53 +01:00
// Override the existing shortcut only if it wasn't customized by the user.
if ( ! sc - > has_meta ( " customized " ) ) {
2022-08-17 07:04:38 +02:00
sc - > set_events ( events ) ;
}
2023-02-16 10:28:04 +01:00
sc - > set_meta ( " original " , events . duplicate ( true ) ) ;
2021-08-08 05:52:00 +02:00
}
2023-02-20 23:11:57 +01:00
Ref < Shortcut > ED_SHORTCUT ( const String & p_path , const String & p_name , Key p_keycode , bool p_physical ) {
2021-06-21 03:34:50 +02:00
PackedInt32Array arr ;
2021-08-13 23:31:57 +02:00
arr . push_back ( ( int32_t ) p_keycode ) ;
2023-02-20 23:11:57 +01:00
return ED_SHORTCUT_ARRAY ( p_path , p_name , arr , p_physical ) ;
2021-06-21 03:34:50 +02:00
}
2023-02-20 23:11:57 +01:00
Ref < Shortcut > ED_SHORTCUT_ARRAY ( const String & p_path , const String & p_name , const PackedInt32Array & p_keycodes , bool p_physical ) {
2021-06-21 03:34:50 +02:00
Array events ;
for ( int i = 0 ; i < p_keycodes . size ( ) ; i + + ) {
Key keycode = ( Key ) p_keycodes [ i ] ;
2022-11-14 15:27:26 +01:00
if ( OS : : get_singleton ( ) - > has_feature ( " macos " ) | | OS : : get_singleton ( ) - > has_feature ( " web_macos " ) | | OS : : get_singleton ( ) - > has_feature ( " web_ios " ) ) {
// Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
if ( keycode = = Key : : KEY_DELETE ) {
keycode = KeyModifierMask : : META | Key : : BACKSPACE ;
}
2021-06-21 03:34:50 +02:00
}
2017-12-26 07:30:36 +01:00
2021-06-21 03:34:50 +02:00
Ref < InputEventKey > ie ;
2021-08-13 23:31:57 +02:00
if ( keycode ! = Key : : NONE ) {
2023-02-20 23:11:57 +01:00
ie = InputEventKey : : create_reference ( keycode , p_physical ) ;
2021-06-21 03:34:50 +02:00
events . push_back ( ie ) ;
}
2016-10-12 22:23:48 +02:00
}
2019-06-01 15:42:22 +02:00
if ( ! EditorSettings : : get_singleton ( ) ) {
2020-09-09 21:53:24 +02:00
Ref < Shortcut > sc ;
2021-06-18 00:03:09 +02:00
sc . instantiate ( ) ;
2019-06-01 15:42:22 +02:00
sc - > set_name ( p_name ) ;
2021-06-21 03:34:50 +02:00
sc - > set_events ( events ) ;
2021-10-13 04:33:53 +02:00
sc - > set_meta ( " original " , events . duplicate ( true ) ) ;
2019-06-01 15:42:22 +02:00
return sc ;
}
2020-09-09 21:53:24 +02:00
Ref < Shortcut > sc = EditorSettings : : get_singleton ( ) - > get_shortcut ( p_path ) ;
2017-10-28 15:40:55 +02:00
if ( sc . is_valid ( ) ) {
sc - > set_name ( p_name ) ; //keep name (the ones that come from disk have no name)
2023-02-21 07:08:53 +01:00
sc - > set_meta ( " original " , events . duplicate ( true ) ) ; //to compare against changes
2017-10-28 15:40:55 +02:00
return sc ;
}
2017-09-25 05:26:41 +02:00
2021-06-18 00:03:09 +02:00
sc . instantiate ( ) ;
2017-10-28 15:40:55 +02:00
sc - > set_name ( p_name ) ;
2021-06-21 03:34:50 +02:00
sc - > set_events ( events ) ;
2021-10-13 04:33:53 +02:00
sc - > set_meta ( " original " , events . duplicate ( true ) ) ; //to compare against changes
2023-02-21 07:08:53 +01:00
EditorSettings : : get_singleton ( ) - > _add_shortcut_default ( p_path , sc ) ;
2017-09-25 05:26:41 +02:00
2017-10-28 15:40:55 +02:00
return sc ;
2017-09-25 05:26:41 +02:00
}
2022-08-31 19:24:04 +02:00
void EditorSettings : : set_builtin_action_override ( const String & p_name , const TypedArray < InputEvent > & p_events ) {
2020-12-07 12:31:51 +01:00
List < Ref < InputEvent > > event_list ;
// Override the whole list, since events may have their order changed or be added, removed or edited.
InputMap : : get_singleton ( ) - > action_erase_events ( p_name ) ;
for ( int i = 0 ; i < p_events . size ( ) ; i + + ) {
event_list . push_back ( p_events [ i ] ) ;
InputMap : : get_singleton ( ) - > action_add_event ( p_name , p_events [ i ] ) ;
}
// Check if the provided event array is same as built-in. If it is, it does not need to be added to the overrides.
// Note that event order must also be the same.
bool same_as_builtin = true ;
2022-05-08 10:09:19 +02:00
HashMap < String , List < Ref < InputEvent > > > : : ConstIterator builtin_default = InputMap : : get_singleton ( ) - > get_builtins_with_feature_overrides_applied ( ) . find ( p_name ) ;
2020-12-07 12:31:51 +01:00
if ( builtin_default ) {
2022-05-08 10:09:19 +02:00
const List < Ref < InputEvent > > & builtin_events = builtin_default - > value ;
2020-12-07 12:31:51 +01:00
2021-08-06 08:30:15 +02:00
// In the editor we only care about key events.
List < Ref < InputEventKey > > builtin_key_events ;
for ( Ref < InputEventKey > iek : builtin_events ) {
if ( iek . is_valid ( ) ) {
builtin_key_events . push_back ( iek ) ;
}
}
if ( p_events . size ( ) = = builtin_key_events . size ( ) ) {
2020-12-07 12:31:51 +01:00
int event_idx = 0 ;
// Check equality of each event.
2021-08-06 08:30:15 +02:00
for ( const Ref < InputEventKey > & E : builtin_key_events ) {
2021-07-16 05:45:57 +02:00
if ( ! E - > is_match ( p_events [ event_idx ] ) ) {
2020-12-07 12:31:51 +01:00
same_as_builtin = false ;
break ;
}
event_idx + + ;
}
} else {
same_as_builtin = false ;
}
}
if ( same_as_builtin & & builtin_action_overrides . has ( p_name ) ) {
builtin_action_overrides . erase ( p_name ) ;
} else {
builtin_action_overrides [ p_name ] = event_list ;
}
// Update the shortcut (if it is used somewhere in the editor) to be the first event of the new list.
if ( shortcuts . has ( p_name ) ) {
2021-06-21 03:34:50 +02:00
shortcuts [ p_name ] - > set_events_list ( & event_list ) ;
2020-12-07 12:31:51 +01:00
}
}
const Array EditorSettings : : get_builtin_action_overrides ( const String & p_name ) const {
2022-05-13 15:04:37 +02:00
HashMap < String , List < Ref < InputEvent > > > : : ConstIterator AO = builtin_action_overrides . find ( p_name ) ;
2020-12-07 12:31:51 +01:00
if ( AO ) {
Array event_array ;
2022-05-13 15:04:37 +02:00
List < Ref < InputEvent > > events_list = AO - > value ;
2021-07-26 17:50:35 +02:00
for ( const Ref < InputEvent > & E : events_list ) {
2021-07-16 05:45:57 +02:00
event_array . push_back ( E ) ;
2020-12-07 12:31:51 +01:00
}
return event_array ;
}
return Array ( ) ;
}
2017-10-28 15:40:55 +02:00
void EditorSettings : : notify_changes ( ) {
_THREAD_SAFE_METHOD_
2017-09-25 05:26:41 +02:00
2017-10-28 15:40:55 +02:00
SceneTree * sml = Object : : cast_to < SceneTree > ( OS : : get_singleton ( ) - > get_main_loop ( ) ) ;
2017-09-25 05:26:41 +02:00
2017-10-28 15:40:55 +02:00
if ( ! sml ) {
return ;
}
2017-09-25 05:26:41 +02:00
2017-10-28 15:40:55 +02:00
Node * root = sml - > get_root ( ) - > get_child ( 0 ) ;
if ( ! root ) {
return ;
}
root - > propagate_notification ( NOTIFICATION_EDITOR_SETTINGS_CHANGED ) ;
2017-09-25 05:26:41 +02:00
}
2014-02-10 02:10:30 +01:00
void EditorSettings : : _bind_methods ( ) {
2017-10-05 20:34:34 +02:00
ClassDB : : bind_method ( D_METHOD ( " has_setting " , " name " ) , & EditorSettings : : has_setting ) ;
ClassDB : : bind_method ( D_METHOD ( " set_setting " , " name " , " value " ) , & EditorSettings : : set_setting ) ;
ClassDB : : bind_method ( D_METHOD ( " get_setting " , " name " ) , & EditorSettings : : get_setting ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " erase " , " property " ) , & EditorSettings : : erase ) ;
2018-01-09 16:52:46 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_initial_value " , " name " , " value " , " update_current " ) , & EditorSettings : : set_initial_value ) ;
2017-10-28 15:40:55 +02:00
ClassDB : : bind_method ( D_METHOD ( " add_property_info " , " info " ) , & EditorSettings : : _add_property_info_bind ) ;
2018-05-16 17:23:20 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_project_metadata " , " section " , " key " , " data " ) , & EditorSettings : : set_project_metadata ) ;
ClassDB : : bind_method ( D_METHOD ( " get_project_metadata " , " section " , " key " , " default " ) , & EditorSettings : : get_project_metadata , DEFVAL ( Variant ( ) ) ) ;
2018-09-18 14:02:59 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_favorites " , " dirs " ) , & EditorSettings : : set_favorites ) ;
ClassDB : : bind_method ( D_METHOD ( " get_favorites " ) , & EditorSettings : : get_favorites ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_recent_dirs " , " dirs " ) , & EditorSettings : : set_recent_dirs ) ;
ClassDB : : bind_method ( D_METHOD ( " get_recent_dirs " ) , & EditorSettings : : get_recent_dirs ) ;
2016-02-27 04:32:00 +01:00
2020-12-07 12:31:51 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_builtin_action_override " , " name " , " actions_list " ) , & EditorSettings : : set_builtin_action_override ) ;
2021-10-15 14:34:11 +02:00
ClassDB : : bind_method ( D_METHOD ( " check_changed_settings_in_group " , " setting_prefix " ) , & EditorSettings : : check_changed_settings_in_group ) ;
ClassDB : : bind_method ( D_METHOD ( " get_changed_settings " ) , & EditorSettings : : get_changed_settings ) ;
ClassDB : : bind_method ( D_METHOD ( " mark_setting_changed " , " setting " ) , & EditorSettings : : mark_setting_changed ) ;
2014-02-10 02:10:30 +01:00
ADD_SIGNAL ( MethodInfo ( " settings_changed " ) ) ;
2019-07-03 09:44:53 +02:00
BIND_CONSTANT ( NOTIFICATION_EDITOR_SETTINGS_CHANGED ) ;
2014-02-10 02:10:30 +01:00
}
EditorSettings : : EditorSettings ( ) {
last_order = 0 ;
2016-05-28 00:58:28 +02:00
2014-02-10 02:10:30 +01:00
_load_defaults ( ) ;
}
EditorSettings : : ~ EditorSettings ( ) {
}