2014-02-10 09:10:30 +08:00
/*************************************************************************/
/* editor_settings.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2018-01-05 07:50:27 +08:00
/* https://godotengine.org */
2014-02-10 09:10:30 +08:00
/*************************************************************************/
2022-01-04 04:27:34 +08:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 09:10:30 +08:00
/* */
/* 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 07:50:27 +08:00
2014-02-10 09:10:30 +08:00
# include "editor_settings.h"
2017-01-16 15:04:19 +08:00
2020-11-08 06:33:38 +08:00
# include "core/config/project_settings.h"
2022-02-14 21:00:03 +08:00
# include "core/input/input_event.h"
2020-12-07 19:31:51 +08:00
# include "core/input/input_map.h"
2022-02-14 21:00:03 +08:00
# include "core/input/shortcut.h"
2018-09-15 20:45:54 +08:00
# include "core/io/certs_compressed.gen.h"
2021-06-11 20:51:48 +08:00
# include "core/io/dir_access.h"
# include "core/io/file_access.h"
2019-12-24 15:17:23 +08:00
# include "core/io/ip.h"
2017-08-26 23:46:49 +08:00
# include "core/io/resource_loader.h"
# include "core/io/resource_saver.h"
2022-02-14 21:00:03 +08:00
# include "core/object/class_db.h"
2017-08-26 23:46:49 +08:00
# include "core/os/keyboard.h"
# include "core/os/os.h"
2022-02-14 21:00:03 +08:00
# include "core/string/translation.h"
2017-08-26 23:46:49 +08:00
# include "core/version.h"
# include "editor/editor_node.h"
2022-02-14 21:00:03 +08:00
# include "editor/editor_paths.h"
2021-12-15 23:01:06 +08:00
# include "editor/editor_translation.h"
2017-03-05 23:44:50 +08:00
# include "scene/main/node.h"
2017-06-27 09:58:03 +08:00
# include "scene/main/scene_tree.h"
2020-03-04 09:51:12 +08:00
# include "scene/main/window.h"
2014-02-10 09:10:30 +08:00
2017-10-28 21:40:55 +08:00
// PRIVATE METHODS
2014-02-10 09:10:30 +08:00
2020-04-02 07:20:12 +08:00
Ref < EditorSettings > EditorSettings : : singleton = nullptr ;
2014-02-10 09:10:30 +08:00
2017-10-28 21:40:55 +08:00
// Properties
2014-02-10 09:10:30 +08:00
2018-01-06 19:40:43 +08: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 20:34:11 +08:00
changed_settings . insert ( p_name ) ;
2021-07-18 05:22:52 +08:00
emit_signal ( SNAME ( " settings_changed " ) ) ;
2018-01-06 19:40:43 +08:00
}
return true ;
}
bool EditorSettings : : _set_only ( const StringName & p_name , const Variant & p_value ) {
2014-02-10 09:10:30 +08:00
_THREAD_SAFE_METHOD_
2016-06-05 08:31:29 +08:00
2020-12-07 19:31:51 +08:00
if ( p_name = = " shortcuts " ) {
2017-03-05 23:44:50 +08:00
Array arr = p_value ;
2021-06-21 09:34:50 +08:00
for ( int i = 0 ; i < arr . size ( ) ; i + + ) {
Dictionary dict = arr [ i ] ;
String name = dict [ " name " ] ;
Array shortcut_events = dict [ " shortcuts " ] ;
2016-06-05 08:31:29 +08:00
2020-09-10 03:53:24 +08:00
Ref < Shortcut > sc ;
2021-06-18 06:03:09 +08:00
sc . instantiate ( ) ;
2021-06-21 09:34:50 +08:00
sc - > set_events ( shortcut_events ) ;
2017-03-05 23:44:50 +08:00
add_shortcut ( name , sc ) ;
2016-06-05 08:31:29 +08:00
}
2020-12-07 19:31:51 +08: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 ] ;
String name = action_dict [ " name " ] ;
Array events = action_dict [ " events " ] ;
InputMap * im = InputMap : : get_singleton ( ) ;
im - > action_erase_events ( name ) ;
builtin_action_overrides [ name ] . clear ( ) ;
for ( int ev_idx = 0 ; ev_idx < events . size ( ) ; ev_idx + + ) {
im - > action_add_event ( name , events [ ev_idx ] ) ;
builtin_action_overrides [ name ] . push_back ( events [ ev_idx ] ) ;
}
}
2018-01-06 19:40:43 +08:00
return false ;
2016-06-05 08:31:29 +08:00
}
2017-12-29 18:03:29 +08:00
bool changed = false ;
2017-11-30 11:11:53 +08:00
if ( p_value . get_type ( ) = = Variant : : NIL ) {
2017-12-29 18:03:29 +08:00
if ( props . has ( p_name ) ) {
props . erase ( p_name ) ;
changed = true ;
}
2017-11-30 11:11:53 +08:00
} else {
2017-12-29 18:03:29 +08:00
if ( props . has ( p_name ) ) {
if ( p_value ! = props [ p_name ] . variant ) {
props [ p_name ] . variant = p_value ;
changed = true ;
}
} else {
2017-03-05 23:44:50 +08:00
props [ p_name ] = VariantContainer ( p_value , last_order + + ) ;
2017-12-29 18:03:29 +08:00
changed = true ;
}
2016-06-12 08:16:14 +08:00
if ( save_changed_setting ) {
2019-06-26 21:08:25 +08:00
if ( ! props [ p_name ] . save ) {
2017-12-29 18:03:29 +08:00
props [ p_name ] . save = true ;
changed = true ;
}
2016-06-12 08:16:14 +08:00
}
2014-02-10 09:10:30 +08:00
}
2018-01-06 19:40:43 +08:00
return changed ;
2014-02-10 09:10:30 +08:00
}
2017-08-26 23:46:49 +08:00
2017-03-05 23:44:50 +08:00
bool EditorSettings : : _get ( const StringName & p_name , Variant & r_ret ) const {
2014-02-10 09:10:30 +08:00
_THREAD_SAFE_METHOD_
2020-12-07 19:31:51 +08:00
if ( p_name = = " shortcuts " ) {
2021-06-21 09:34:50 +08:00
Array save_array ;
2021-10-13 10:33:53 +08:00
const OrderedHashMap < String , List < Ref < InputEvent > > > & builtin_list = InputMap : : get_singleton ( ) - > get_builtins ( ) ;
2021-06-21 09:34:50 +08:00
for ( const KeyValue < String , Ref < Shortcut > > & shortcut_definition : shortcuts ) {
Ref < Shortcut > sc = shortcut_definition . value ;
2016-06-05 08:31:29 +08:00
2021-10-13 10:33:53 +08:00
if ( builtin_list . has ( shortcut_definition . key ) ) {
2020-12-07 19:31:51 +08: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 14:03:58 +08:00
// If the builtin is overridden, it will be saved in the "builtin_action_overrides" section below.
2020-12-07 19:31:51 +08:00
continue ;
}
2021-10-13 10:33:53 +08: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,
// we still want save the shortcut in this case so that shortcuts that the user has customised are not reset,
// 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 09:34:50 +08:00
}
2016-07-04 06:13:45 +08:00
2021-06-21 09:34:50 +08: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 06:13:45 +08:00
}
2021-06-21 09:34:50 +08:00
save_array . push_back ( dict ) ;
2016-06-05 08:31:29 +08:00
}
2021-06-21 09:34:50 +08:00
r_ret = save_array ;
2016-06-05 08:31:29 +08:00
return true ;
2020-12-07 19:31:51 +08:00
} else if ( p_name = = " builtin_action_overrides " ) {
Array actions_arr ;
2021-06-21 09:34:50 +08:00
for ( const KeyValue < String , List < Ref < InputEvent > > > & action_override : builtin_action_overrides ) {
List < Ref < InputEvent > > events = action_override . value ;
2020-12-07 19:31:51 +08:00
Dictionary action_dict ;
2021-06-21 09:34:50 +08:00
action_dict [ " name " ] = action_override . key ;
2020-12-07 19:31:51 +08:00
2021-06-21 09:34:50 +08:00
// Convert the list to an array, and only keep key events as this is for the editor.
2020-12-07 19:31:51 +08:00
Array events_arr ;
2021-06-21 09:34:50 +08:00
for ( const Ref < InputEvent > & ie : events ) {
Ref < InputEventKey > iek = ie ;
if ( iek . is_valid ( ) ) {
events_arr . append ( iek ) ;
}
2020-12-07 19:31:51 +08:00
}
2021-06-21 09:34:50 +08: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 19:31:51 +08:00
2021-06-21 09:34:50 +08:00
// Don't save if same as default.
if ( same ) {
continue ;
}
action_dict [ " events " ] = events_arr ;
2020-12-07 19:31:51 +08:00
actions_arr . push_back ( action_dict ) ;
}
r_ret = actions_arr ;
return true ;
2016-06-05 08:31:29 +08:00
}
2017-03-05 23:44:50 +08:00
const VariantContainer * v = props . getptr ( p_name ) ;
2017-01-06 06:41:36 +08:00
if ( ! v ) {
2019-11-07 16:44:15 +08:00
WARN_PRINT ( " EditorSettings::_get - Property not found: " + String ( p_name ) ) ;
2014-02-10 09:10:30 +08:00
return false ;
2017-01-06 06:41:36 +08:00
}
2014-02-10 09:10:30 +08:00
r_ret = v - > variant ;
return true ;
}
2017-09-25 11:26:41 +08: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-21 01:34:13 +08:00
props [ p_name ] . has_default_value = true ;
2017-09-25 11:26:41 +08:00
}
2014-02-10 09:10:30 +08:00
struct _EVCSort {
String name ;
2020-11-24 17:12:55 +08:00
Variant : : Type type = Variant : : Type : : NIL ;
int order = 0 ;
bool save = false ;
bool restart_if_changed = false ;
2014-02-10 09:10:30 +08:00
2017-03-05 23:44:50 +08:00
bool operator < ( const _EVCSort & p_vcs ) const { return order < p_vcs . order ; }
2014-02-10 09:10:30 +08:00
} ;
void EditorSettings : : _get_property_list ( List < PropertyInfo > * p_list ) const {
_THREAD_SAFE_METHOD_
2020-04-02 07:20:12 +08:00
const String * k = nullptr ;
2014-02-10 09:10:30 +08:00
Set < _EVCSort > vclist ;
2017-03-05 23:44:50 +08:00
while ( ( k = props . next ( k ) ) ) {
const VariantContainer * v = props . getptr ( * k ) ;
2014-02-10 09:10:30 +08:00
2020-05-14 22:41:43 +08:00
if ( v - > hide_from_editor ) {
2014-02-10 09:10:30 +08:00
continue ;
2020-05-14 22:41:43 +08:00
}
2014-02-10 09:10:30 +08:00
_EVCSort vc ;
2017-03-05 23:44:50 +08:00
vc . name = * k ;
vc . order = v - > order ;
vc . type = v - > variant . get_type ( ) ;
vc . save = v - > save ;
2019-03-06 23:10:36 +08: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-20 05:58:15 +08:00
vc . restart_if_changed = v - > restart_if_changed ;
2014-02-10 09:10:30 +08:00
vclist . insert ( vc ) ;
}
2017-03-05 23:44:50 +08:00
for ( Set < _EVCSort > : : Element * E = vclist . front ( ) ; E ; E = E - > next ( ) ) {
2021-07-01 09:24:34 +08:00
uint32_t pusage = PROPERTY_USAGE_NONE ;
2016-07-04 06:13:45 +08:00
if ( E - > get ( ) . save | | ! optimize_save ) {
2021-07-01 09:24:34 +08:00
pusage | = PROPERTY_USAGE_STORAGE ;
2016-06-12 08:16:14 +08:00
}
2016-06-13 02:34:58 +08:00
if ( ! E - > get ( ) . name . begins_with ( " _ " ) & & ! E - > get ( ) . name . begins_with ( " projects/ " ) ) {
2021-07-01 09:24:34 +08:00
pusage | = PROPERTY_USAGE_EDITOR ;
2016-06-12 08:16:14 +08:00
} else {
2021-07-01 09:24:34 +08:00
pusage | = PROPERTY_USAGE_STORAGE ; //hiddens must always be saved
2016-06-12 08:16:14 +08:00
}
2014-02-10 09:10:30 +08:00
PropertyInfo pi ( E - > get ( ) . type , E - > get ( ) . name ) ;
2021-07-01 09:24:34 +08:00
pi . usage = pusage ;
2020-05-14 22:41:43 +08:00
if ( hints . has ( E - > get ( ) . name ) ) {
2017-03-05 23:44:50 +08:00
pi = hints [ E - > get ( ) . name ] ;
2020-05-14 22:41:43 +08:00
}
2014-02-10 09:10:30 +08:00
2018-07-20 05:58:15 +08:00
if ( E - > get ( ) . restart_if_changed ) {
pi . usage | = PROPERTY_USAGE_RESTART_IF_CHANGED ;
}
2017-03-05 23:44:50 +08:00
p_list - > push_back ( pi ) ;
2014-02-10 09:10:30 +08:00
}
2016-06-05 08:31:29 +08:00
2021-11-04 06:06:17 +08: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 09:10:30 +08:00
}
2017-10-28 21:40:55 +08: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-06 02:34:34 +08:00
2017-10-28 21:40:55 +08: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 09:10:30 +08:00
2020-05-14 22:41:43 +08:00
if ( p_info . has ( " hint " ) ) {
2017-10-28 21:40:55 +08:00
pinfo . hint = PropertyHint ( p_info [ " hint " ] . operator int ( ) ) ;
2020-05-14 22:41:43 +08:00
}
if ( p_info . has ( " hint_string " ) ) {
2017-10-28 21:40:55 +08:00
pinfo . hint_string = p_info [ " hint_string " ] ;
2020-05-14 22:41:43 +08:00
}
2014-02-10 09:10:30 +08:00
2017-10-28 21:40:55 +08:00
add_property_hint ( pinfo ) ;
2014-02-10 09:10:30 +08:00
}
2017-10-28 21:40:55 +08:00
// Default configs
2017-10-29 05:25:28 +08:00
bool EditorSettings : : has_default_value ( const String & p_setting ) const {
_THREAD_SAFE_METHOD_
2020-05-14 22:41:43 +08:00
if ( ! props . has ( p_setting ) ) {
2017-10-29 05:25:28 +08:00
return false ;
2020-05-14 22:41:43 +08:00
}
2017-11-21 01:34:13 +08:00
return props [ p_setting ] . has_default_value ;
2017-10-29 05:25:28 +08:00
}
2014-02-10 09:10:30 +08:00
2017-10-28 21:40:55 +08:00
void EditorSettings : : _load_defaults ( Ref < ConfigFile > p_extra_config ) {
2014-02-10 09:10:30 +08:00
_THREAD_SAFE_METHOD_
2021-08-16 13:30:24 +08: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 09:10:30 +08:00
2018-12-12 15:18:24 +08:00
/* Languages */
2017-10-28 21:40:55 +08:00
{
String lang_hint = " en " ;
String host_lang = OS : : get_singleton ( ) - > get_locale ( ) ;
2014-02-10 09:10:30 +08:00
2020-09-03 19:22:16 +08: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 20:32:01 +08:00
2020-12-15 20:04:21 +08:00
if ( ! locales_to_skip . is_empty ( ) ) {
2020-09-03 19:22:16 +08:00
WARN_PRINT ( " Some locales are not properly supported by selected Text Server and are disabled. " ) ;
}
2017-09-25 11:26:41 +08:00
2020-09-03 19:22:16 +08:00
String best ;
2021-09-23 19:08:50 +08:00
int best_score = 0 ;
2021-12-15 23:01:06 +08:00
for ( const String & locale : get_editor_locales ( ) ) {
2019-05-21 20:32:01 +08: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-02 02:19:13 +08:00
if ( locales_to_skip . has ( lang_code ) ) {
2019-05-21 20:32:01 +08:00
continue ;
}
2017-10-28 21:40:55 +08:00
lang_hint + = " , " ;
lang_hint + = locale ;
2014-02-10 09:10:30 +08:00
2021-09-23 19:08:50 +08:00
int score = TranslationServer : : get_singleton ( ) - > compare_locales ( host_lang , locale ) ;
2022-01-25 00:58:16 +08:00
if ( score > 0 & & score > = best_score ) {
2017-10-28 21:40:55 +08:00
best = locale ;
2021-09-23 19:08:50 +08:00
best_score = score ;
if ( score = = 10 ) {
break ; // Exact match, skip the rest.
}
2017-10-28 21:40:55 +08:00
}
}
2021-09-23 19:08:50 +08:00
if ( best_score = = 0 ) {
2017-10-28 21:40:55 +08:00
best = " en " ;
}
2017-08-04 00:23:46 +08:00
2021-08-16 13:30:24 +08: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 21:40:55 +08:00
}
2017-08-04 00:23:46 +08:00
2018-12-12 15:18:24 +08:00
/* Interface */
// Editor
2021-01-18 09:39:46 +08:00
// Display what the Auto display scale setting effectively corresponds to.
2021-08-16 13:30:24 +08: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 23:07:57 +08:00
2022-03-21 08:53:30 +08:00
_initial_set ( " interface/editor/debug/enable_pseudolocalization " , false ) ;
set_restart_if_changed ( " interface/editor/debug/enable_pseudolocalization " , true ) ;
2021-08-08 23:07:57 +08:00
// Use pseudolocalization in editor.
2021-08-16 13:30:24 +08: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 14:20:09 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " interface/editor/main_font_size " , 14 , " 8,48,1 " )
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " interface/editor/code_font_size " , 14 , " 8,48,1 " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/code_font_contextual_ligatures " , 0 , " Default,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set " )
2020-09-03 19:22:16 +08:00
_initial_set ( " interface/editor/code_font_custom_opentype_features " , " " ) ;
2020-10-23 00:40:18 +08:00
_initial_set ( " interface/editor/code_font_custom_variations " , " " ) ;
2019-07-28 07:10:51 +08:00
_initial_set ( " interface/editor/font_antialiased " , true ) ;
2021-01-18 09:39:46 +08:00
# ifdef OSX_ENABLED
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/font_hinting " , 0 , " Auto (None),None,Light,Normal " )
2021-01-18 09:39:46 +08:00
# else
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " interface/editor/font_hinting " , 0 , " Auto (Light),None,Light,Normal " )
2021-01-18 09:39:46 +08:00
# endif
2022-01-10 16:13:22 +08: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-03-25 16:54:32 +08: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 13:30:24 +08: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 21:40:55 +08:00
_initial_set ( " interface/editor/separate_distraction_mode " , false ) ;
2019-07-23 13:05:29 +08:00
_initial_set ( " interface/editor/automatically_open_screenshots " , true ) ;
2021-08-16 13:30:24 +08: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-09 00:32:49 +08:00
_initial_set ( " interface/editor/mouse_extra_buttons_navigate_history " , true ) ;
2017-10-28 21:40:55 +08:00
_initial_set ( " interface/editor/save_each_scene_on_quit " , true ) ; // Regression
2022-01-08 09:32:53 +08: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-13 02:46:08 +08:00
2021-01-02 02:41:11 +08:00
// Inspector
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " interface/inspector/max_array_dictionary_items_per_page " , 20 , " 10,100,1 " )
2021-01-02 02:41:11 +08:00
2018-12-12 15:18:24 +08:00
// Theme
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_ENUM , " interface/theme/preset " , " Default " , " Default,Breeze Dark,Godot 2,Grey,Light,Solarized (Dark),Solarized (Light),Custom " )
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 " )
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-04 00:23:46 +08:00
2018-12-12 15:18:24 +08:00
// Scene tabs
2022-03-13 09:03:26 +08: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 21:40:55 +08:00
_initial_set ( " interface/scene_tabs/show_thumbnail_on_hover " , true ) ;
2022-02-03 13:45:31 +08:00
EDITOR_SETTING_USAGE ( Variant : : INT , PROPERTY_HINT_RANGE , " interface/scene_tabs/maximum_width " , 350 , " 0,9999,1 " , PROPERTY_USAGE_DEFAULT )
2018-12-12 15:18:24 +08:00
_initial_set ( " interface/scene_tabs/show_script_button " , false ) ;
2017-08-04 00:23:46 +08:00
2018-12-12 15:18:24 +08:00
/* Filesystem */
// Directories
2021-08-16 13:30:24 +08: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-13 02:46:08 +08:00
2018-12-12 15:18:24 +08: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 13:30:24 +08: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 15:18:24 +08:00
/* Docks */
// SceneTree
_initial_set ( " docks/scene_tree/start_create_dialog_fully_expanded " , false ) ;
2021-08-10 01:14:06 +08:00
_initial_set ( " docks/scene_tree/auto_expand_to_selected " , true ) ;
2018-12-12 15:18:24 +08:00
// FileSystem
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " docks/filesystem/thumbnail_size " , 64 , " 32,128,16 " )
2018-12-12 15:18:24 +08:00
_initial_set ( " docks/filesystem/always_show_folders " , true ) ;
2021-09-24 05:09:15 +08:00
_initial_set ( " docks/filesystem/textfile_extensions " , " txt,md,cfg,ini,log,json,yml,yaml,toml " ) ;
2018-12-12 15:18:24 +08:00
// Property editor
2021-02-11 04:18:45 +08:00
_initial_set ( " docks/property_editor/auto_refresh_interval " , 0.2 ) ; //update 5 times per second by default
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " docks/property_editor/subresource_hue_tint " , 0.75 , " 0,1,0.01 " )
2018-12-12 15:18:24 +08:00
/* Text editor */
// Theme
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : STRING , PROPERTY_HINT_ENUM , " text_editor/theme/color_theme " , " Default " , " Default,Godot 2,Custom " )
2014-02-10 09:10:30 +08:00
2021-08-16 01:14:46 +08:00
// Theme: Highlighting
2021-05-27 16:22:36 +08:00
_load_godot2_text_editor_theme ( ) ;
2014-02-10 09:10:30 +08:00
2019-09-01 19:28:57 +08:00
// Appearance
2021-08-16 01:14:46 +08:00
// Appearance: Caret
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " text_editor/appearance/caret/type " , 0 , " Line,Block " )
2021-08-16 01:14:46 +08:00
_initial_set ( " text_editor/appearance/caret/caret_blink " , true ) ;
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " text_editor/appearance/caret/caret_blink_speed " , 0.5 , " 0.1,10,0.01 " )
2021-08-16 01:14:46 +08: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 13:30:24 +08: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-16 01:14:46 +08: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 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/appearance/minimap/minimap_width " , 80 , " 50,250,1 " )
2021-08-16 01:14:46 +08:00
// Appearance: Lines
_initial_set ( " text_editor/appearance/lines/code_folding " , true ) ;
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " text_editor/appearance/lines/word_wrap " , 0 , " None,Boundary " )
2021-08-16 01:14:46 +08:00
// Appearance: Whitespace
_initial_set ( " text_editor/appearance/whitespace/draw_tabs " , true ) ;
_initial_set ( " text_editor/appearance/whitespace/draw_spaces " , false ) ;
2022-03-21 09:00:58 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/appearance/whitespace/line_spacing " , 4 , " 0,50,1 " )
2021-08-16 01:14:46 +08: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 21:40:49 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/behavior/navigation/v_scroll_speed " , 80 , " 1,10000,1 " )
2021-08-16 01:14:46 +08:00
// Behavior: Indent
2021-08-16 13:30:24 +08: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-16 01:14:46 +08: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-07 04:39:19 +08:00
_initial_set ( " text_editor/behavior/files/auto_reload_scripts_on_external_change " , false ) ;
2019-09-01 19:28:57 +08:00
// Script list
_initial_set ( " text_editor/script_list/show_members_overview " , true ) ;
2021-08-16 01:14:46 +08:00
_initial_set ( " text_editor/script_list/sort_members_outline_alphabetically " , false ) ;
2014-02-10 09:10:30 +08:00
2018-12-12 15:18:24 +08:00
// Completion
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " text_editor/completion/idle_parse_delay " , 2.0 , " 0.1,10,0.01 " )
2019-07-19 03:34:28 +08:00
_initial_set ( " text_editor/completion/auto_brace_complete " , true ) ;
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " text_editor/completion/code_complete_delay " , 0.3 , " 0.01,5,0.01 " )
2018-01-06 19:40:43 +08:00
_initial_set ( " text_editor/completion/put_callhint_tooltip_below_current_line " , true ) ;
2017-10-28 21:40:55 +08:00
_initial_set ( " text_editor/completion/complete_file_paths " , true ) ;
2018-05-30 10:16:59 +08:00
_initial_set ( " text_editor/completion/add_type_hints " , false ) ;
2018-12-18 09:53:54 +08:00
_initial_set ( " text_editor/completion/use_single_quotes " , false ) ;
2014-02-10 09:10:30 +08:00
2018-12-12 15:18:24 +08:00
// Help
_initial_set ( " text_editor/help/show_help_index " , true ) ;
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/help/help_font_size " , 15 , " 8,48,1 " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/help/help_source_font_size " , 14 , " 8,48,1 " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " text_editor/help/help_title_font_size " , 23 , " 8,48,1 " )
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " text_editor/help/class_reference_examples " , 0 , " GDScript,C#,GDScript and C# " )
2018-12-12 15:18:24 +08:00
/* Editors */
2014-02-10 09:10:30 +08:00
2018-12-12 15:18:24 +08:00
// GridMap
2017-10-28 21:40:55 +08:00
_initial_set ( " editors/grid_map/pick_distance " , 5000.0 ) ;
2014-02-10 09:10:30 +08:00
2018-12-12 15:18:24 +08:00
// 3D
2021-08-16 13:30:24 +08: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 07:43:20 +08:00
2020-12-29 14:35:59 +08:00
// Use a similar color to the 2D editor selection.
2021-08-16 13:30:24 +08: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-07 04:39:19 +08: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 14:35:59 +08:00
2019-04-21 18:15:45 +08:00
// If a line is a multiple of this, it uses the primary grid color.
2020-11-22 04:35:23 +08: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 13:30:24 +08: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 18:15:45 +08: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 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " editors/3d/grid_division_level_max " , 2 , " -1,3,1 " )
2019-04-21 18:15:45 +08:00
// Lower values produce graphical artifacts regardless of view clipping planes, so limit to -2 as a lower bound.
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " editors/3d/grid_division_level_min " , 0 , " -2,2,1 " )
2019-04-21 18:15:45 +08:00
// -0.2 seems like a sensible default. -1.0 gives Blender-like behavior, 0.5 gives huge grids.
2021-08-16 13:30:24 +08: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 18:15:45 +08: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 09:10:30 +08:00
2019-10-31 21:32:46 +08: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-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/default_fov " , 70.0 , " 1,179,0.1 " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/default_z_near " , 0.05 , " 0.01,10,0.01,or_greater " )
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/3d/default_z_far " , 4000.0 , " 0.1,4000,0.1,or_greater " )
2017-10-28 21:40:55 +08:00
2018-12-12 15:18:24 +08:00
// 3D: Navigation
2020-08-15 19:18:01 +08:00
_initial_set ( " editors/3d/navigation/invert_x_axis " , false ) ;
2021-08-16 13:30:24 +08: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 21:40:55 +08:00
2021-07-02 15:27:12 +08:00
_initial_set ( " editors/3d/navigation/emulate_numpad " , false ) ;
2017-10-28 21:40:55 +08:00
_initial_set ( " editors/3d/navigation/emulate_3_button_mouse " , false ) ;
2021-08-16 13:30:24 +08: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 21:40:55 +08:00
_initial_set ( " editors/3d/navigation/warped_mouse_panning " , true ) ;
2018-12-12 15:18:24 +08:00
// 3D: Navigation feel
2020-01-14 07:26:26 +08: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 21:40:55 +08:00
2018-12-12 15:18:24 +08:00
// 3D: Freelook
2021-08-16 13:30:24 +08: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 07:26:26 +08: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 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/3d/freelook/freelook_activation_modifier " , 0 , " None,Shift,Alt,Meta,Ctrl " )
2017-10-28 21:40:55 +08:00
_initial_set ( " editors/3d/freelook/freelook_speed_zoom_link " , false ) ;
2018-12-12 15:18:24 +08:00
// 2D
2018-08-18 23:32:09 +08:00
_initial_set ( " editors/2d/grid_color " , Color ( 1.0 , 1.0 , 1.0 , 0.07 ) ) ;
2017-12-06 04:42:33 +08:00
_initial_set ( " editors/2d/guides_color " , Color ( 0.6 , 0.0 , 0.8 ) ) ;
2019-04-05 16:18:21 +08:00
_initial_set ( " editors/2d/smart_snapping_line_color " , Color ( 0.9 , 0.1 , 0.1 ) ) ;
2017-10-28 21:40:55 +08: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-04 02:02:24 +08: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 22:54:04 +08:00
_initial_set ( " editors/2d/bone_outline_size " , 2 ) ;
2018-09-24 21:16:40 +08:00
_initial_set ( " editors/2d/viewport_border_color " , Color ( 0.4 , 0.4 , 1.0 , 0.4 ) ) ;
2019-06-25 03:15:26 +08:00
_initial_set ( " editors/2d/constrain_editor_view " , true ) ;
2022-01-20 02:59:12 +08: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 20:49:53 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " editors/panning/sub_editors_panning_scheme " , 0 , " Scroll Zooms,Scroll Pans " ) ;
2022-01-20 02:59:12 +08: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 21:40:55 +08:00
2021-05-21 23:28:28 +08: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 15:18:24 +08:00
// Polygon editor
2021-08-23 23:59:19 +08:00
_initial_set ( " editors/polygon_editor/point_grab_radius " , 8 ) ;
_initial_set ( " editors/polygon_editor/show_previous_outline " , true ) ;
2017-10-28 21:40:55 +08:00
2018-12-12 15:18:24 +08:00
// Animation
_initial_set ( " editors/animation/autorename_animation_tracks " , true ) ;
_initial_set ( " editors/animation/confirm_insert_track " , true ) ;
2020-12-20 18:46:44 +08:00
_initial_set ( " editors/animation/default_create_bezier_tracks " , false ) ;
_initial_set ( " editors/animation/default_create_reset_tracks " , true ) ;
2018-12-12 15:18:24 +08: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 22:37:05 +08:00
// Visual editors
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : FLOAT , PROPERTY_HINT_RANGE , " editors/visual_editors/minimap_opacity " , 0.85 , " 0.0,1.0,0.01 " )
2021-01-25 22:37:05 +08:00
2018-12-12 15:18:24 +08:00
/* Run */
// Window placement
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " run/window_placement/rect " , 1 , " Top Left,Centered,Custom Position,Force Maximized,Force Fullscreen " )
2018-08-18 21:30:00 +08:00
String screen_hints = " Same as Editor,Previous Monitor,Next Monitor " ;
2020-03-03 21:36:29 +08:00
for ( int i = 0 ; i < DisplayServer : : get_singleton ( ) - > get_screen_count ( ) ; i + + ) {
2017-10-28 21:40:55 +08:00
screen_hints + = " ,Monitor " + itos ( i + 1 ) ;
}
_initial_set ( " run/window_placement/rect_custom_position " , Vector2 ( ) ) ;
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " run/window_placement/screen " , 0 , screen_hints )
2017-10-28 21:40:55 +08:00
2018-12-12 15:18:24 +08:00
// Auto save
2017-10-28 21:40:55 +08:00
_initial_set ( " run/auto_save/save_before_running " , true ) ;
2018-12-12 15:18:24 +08:00
// Output
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " run/output/font_size " , 13 , " 8,48,1 " )
2017-10-28 21:40:55 +08: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 23:05:06 +08:00
/* Network */
// Debug
_initial_set ( " network/debug/remote_host " , " 127.0.0.1 " ) ; // Hints provided in setup_network
2021-08-16 13:30:24 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_RANGE , " network/debug/remote_port " , 6007 , " 1,65535,1 " )
2019-08-21 23:05:06 +08:00
// SSL
2022-03-26 21:32:59 +08:00
EDITOR_SETTING_USAGE ( Variant : : STRING , PROPERTY_HINT_GLOBAL_FILE , " network/ssl/editor_ssl_certificates " , _SYSTEM_CERTS_PATH , " *.crt,*.pem " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED ) ;
2019-08-21 23:05:06 +08:00
2022-03-07 04:39:19 +08:00
// Profiler
_initial_set ( " debugger/profiler_frame_history_size " , 600 ) ;
2022-03-20 20:56:11 +08: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 15:18:24 +08:00
/* Extra config */
2017-10-28 21:40:55 +08:00
2021-11-08 05:50:29 +08:00
EDITOR_SETTING ( Variant : : INT , PROPERTY_HINT_ENUM , " project_manager/sorting_order " , 0 , " Last Edited,Name,Path " )
2018-12-13 04:12:41 +08:00
2017-10-28 21:40:55 +08: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 + + ) {
String name = list [ i ] . replace ( " / " , " :: " ) ;
set ( " projects/ " + name , list [ i ] ) ;
2021-06-09 16:47:32 +08:00
}
}
2017-10-28 21:40:55 +08:00
if ( p_extra_config - > has_section ( " presets " ) ) {
List < String > keys ;
p_extra_config - > get_section_keys ( " presets " , & keys ) ;
2021-07-24 21:46:25 +08:00
for ( const String & key : keys ) {
2017-10-28 21:40:55 +08:00
Variant val = p_extra_config - > get_value ( " presets " , key ) ;
set ( key , val ) ;
2021-06-09 16:47:32 +08:00
}
}
}
2017-10-28 21:40:55 +08:00
}
2021-05-27 16:22:36 +08: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-16 01:14:46 +08: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 23:59:01 +08:00
_initial_set ( " text_editor/theme/highlighting/completion_existing_color " , Color ( 0.87 , 0.87 , 0.87 , 0.13 ) ) ;
2022-02-14 21:41:22 +08:00
_initial_set ( " text_editor/theme/highlighting/completion_scroll_color " , Color ( 1 , 1 , 1 , 0.29 ) ) ;
2021-08-16 01:14:46 +08: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 ) ) ;
_initial_set ( " text_editor/theme/highlighting/text_selected_color " , Color ( 0 , 0 , 0 ) ) ;
_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 21:40:55 +08: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 20:06:24 +08:00
List < String > keys ;
props . get_key_list ( & keys ) ;
keys . sort ( ) ;
2021-07-16 11:45:57 +08:00
for ( const String & key : keys ) {
2021-08-16 01:14:46 +08: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 20:06:24 +08:00
}
}
2018-04-13 05:26:15 +08:00
2017-10-28 21:40:55 +08:00
Error err = cf - > save ( p_file ) ;
2019-06-26 21:08:25 +08:00
return err = = OK ;
2017-10-28 21:40:55 +08:00
}
2019-05-23 23:18:24 +08:00
bool EditorSettings : : _is_default_text_editor_theme ( String p_theme_name ) {
2021-05-27 16:22:36 +08:00
return p_theme_name = = " default " | | p_theme_name = = " godot 2 " | | p_theme_name = = " custom " ;
2019-05-23 23:18:24 +08:00
}
2017-10-28 21:40:55 +08:00
// PUBLIC METHODS
EditorSettings * EditorSettings : : get_singleton ( ) {
return singleton . ptr ( ) ;
}
void EditorSettings : : create ( ) {
2021-06-09 16:47:32 +08: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 22:41:43 +08:00
if ( singleton . ptr ( ) ) {
2021-06-09 16:47:32 +08:00
ERR_PRINT ( " Can't recreate EditorSettings as it already exists. " ) ;
return ;
2020-05-14 22:41:43 +08:00
}
2017-10-28 21:40:55 +08:00
2021-07-12 06:30:33 +08:00
GDREGISTER_CLASS ( EditorSettings ) ; // Otherwise it can't be unserialized.
2021-06-09 16:47:32 +08:00
String config_file_path ;
2017-10-28 21:40:55 +08:00
Ref < ConfigFile > extra_config = memnew ( ConfigFile ) ;
2021-06-09 16:47:32 +08: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 08:25:11 +08:00
if ( EditorPaths : : get_singleton ( ) - > is_self_contained ( ) ) {
Error err = extra_config - > load ( EditorPaths : : get_singleton ( ) - > get_self_contained_file ( ) ) ;
2019-08-07 18:54:30 +08:00
if ( err ! = OK ) {
2021-06-09 16:47:32 +08:00
ERR_PRINT ( " Can't load extra config from path: " + EditorPaths : : get_singleton ( ) - > get_self_contained_file ( ) ) ;
2019-08-07 18:54:30 +08:00
}
2017-10-28 21:40:55 +08:00
}
2021-05-25 08:25:11 +08:00
if ( EditorPaths : : get_singleton ( ) - > are_paths_valid ( ) ) {
2021-06-09 16:47:32 +08:00
// Validate editor config file.
2022-03-23 17:08:58 +08:00
Ref < DirAccess > dir = DirAccess : : open ( EditorPaths : : get_singleton ( ) - > get_config_dir ( ) ) ;
2017-11-20 14:40:06 +08:00
String config_file_name = " editor_settings- " + itos ( VERSION_MAJOR ) + " .tres " ;
2021-05-25 08:25:11 +08:00
config_file_path = EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . plus_file ( config_file_name ) ;
2017-01-12 05:38:00 +08:00
if ( ! dir - > file_exists ( config_file_name ) ) {
2017-01-06 06:41:36 +08:00
goto fail ;
2014-02-10 09:10:30 +08:00
}
2017-11-17 22:50:18 +08:00
singleton = ResourceLoader : : load ( config_file_path , " EditorSettings " ) ;
2016-06-05 08:31:29 +08:00
2014-02-10 09:10:30 +08:00
if ( singleton . is_null ( ) ) {
2021-06-09 16:47:32 +08:00
ERR_PRINT ( " Could not load editor settings from path: " + config_file_path ) ;
2014-02-10 09:10:30 +08:00
goto fail ;
}
2017-03-05 23:44:50 +08:00
singleton - > save_changed_setting = true ;
singleton - > config_file_path = config_file_path ;
2014-02-10 09:10:30 +08:00
2018-08-24 14:47:34 +08:00
print_verbose ( " EditorSettings: Load OK! " ) ;
2014-02-10 09:10:30 +08:00
2016-05-28 06:58:28 +08:00
singleton - > setup_language ( ) ;
2015-08-06 13:37:40 +08:00
singleton - > setup_network ( ) ;
2022-02-03 08:21:52 +08:00
singleton - > load_favorites_and_recent_dirs ( ) ;
2016-04-12 22:45:31 +08:00
singleton - > list_text_editor_themes ( ) ;
2014-02-10 09:10:30 +08:00
return ;
}
2017-10-28 21:40:55 +08:00
fail :
// patch init projects
2021-05-25 08:25:11 +08:00
String exe_path = OS : : get_singleton ( ) - > get_executable_path ( ) . get_base_dir ( ) ;
2017-10-28 21:40:55 +08: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 + + ) {
2019-06-16 20:31:57 +08:00
list . write [ i ] = exe_path . plus_file ( list [ i ] ) ;
2021-06-09 16:47:32 +08:00
}
2017-10-28 21:40:55 +08:00
extra_config - > set_value ( " init_projects " , " list " , list ) ;
2021-06-09 16:47:32 +08:00
}
2017-01-06 06:41:36 +08:00
2017-10-28 21:40:55 +08:00
singleton = Ref < EditorSettings > ( memnew ( EditorSettings ) ) ;
singleton - > save_changed_setting = true ;
singleton - > config_file_path = config_file_path ;
singleton - > _load_defaults ( extra_config ) ;
singleton - > setup_language ( ) ;
singleton - > setup_network ( ) ;
singleton - > list_text_editor_themes ( ) ;
}
2017-01-06 06:41:36 +08:00
2017-10-28 21:40:55 +08:00
void EditorSettings : : setup_language ( ) {
2022-03-21 08:53:30 +08:00
TranslationServer : : get_singleton ( ) - > set_editor_pseudolocalization ( get ( " interface/editor/debug/enable_pseudolocalization " ) ) ;
2017-10-28 21:40:55 +08:00
String lang = get ( " interface/editor/editor_language " ) ;
2020-05-14 22:41:43 +08:00
if ( lang = = " en " ) {
2020-03-19 01:34:36 +08:00
return ; // Default, nothing to do.
2020-05-14 22:41:43 +08:00
}
2020-03-19 01:34:36 +08:00
// Load editor translation for configured/detected locale.
2021-12-15 23:01:06 +08:00
load_editor_translations ( lang ) ;
2020-03-19 01:34:36 +08:00
// Load class reference translation.
2021-12-15 23:01:06 +08:00
load_doc_translations ( lang ) ;
2017-10-28 21:40:55 +08:00
}
2017-09-19 08:30:48 +08:00
2017-10-28 21:40:55 +08:00
void EditorSettings : : setup_network ( ) {
2021-05-06 08:48:18 +08:00
List < IPAddress > local_ip ;
2017-10-28 21:40:55 +08: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 23:05:06 +08:00
String selected = " 127.0.0.1 " ;
2017-01-06 06:41:36 +08:00
2019-08-21 23:05:06 +08:00
// Check that current remote_host is a valid interface address and populate hints.
2021-07-24 21:46:25 +08:00
for ( const IPAddress & ip : local_ip ) {
2017-10-28 21:40:55 +08:00
// link-local IPv6 addresses don't work, skipping them
2021-07-16 11:45:57 +08:00
if ( String ( ip ) . begins_with ( " fe80:0:0:0: " ) ) { // fe80::/64
2017-10-28 21:40:55 +08:00
continue ;
2020-05-14 22:41:43 +08:00
}
2019-03-31 22:57:23 +08:00
// Same goes for IPv4 link-local (APIPA) addresses.
2021-07-16 11:45:57 +08:00
if ( String ( ip ) . begins_with ( " 169.254. " ) ) { // 169.254.0.0/16
2019-03-31 22:57:23 +08:00
continue ;
2020-05-14 22:41:43 +08:00
}
2019-08-21 23:05:06 +08:00
// Select current IP (found)
2020-05-14 22:41:43 +08:00
if ( ip = = current ) {
2019-08-21 23:05:06 +08:00
selected = ip ;
2020-05-14 22:41:43 +08:00
}
2021-12-09 17:42:46 +08:00
if ( ! hint . is_empty ( ) ) {
2017-10-28 21:40:55 +08:00
hint + = " , " ;
2020-05-14 22:41:43 +08:00
}
2017-10-28 21:40:55 +08:00
hint + = ip ;
}
2017-05-02 02:57:35 +08:00
2019-08-21 23:05:06 +08:00
// Add hints with valid IP addresses to remote_host property.
2017-10-28 21:40:55 +08:00
add_property_hint ( PropertyInfo ( Variant : : STRING , " network/debug/remote_host " , PROPERTY_HINT_ENUM , hint ) ) ;
2019-08-21 23:05:06 +08:00
// Fix potentially invalid remote_host due to network change.
set ( " network/debug/remote_host " , selected ) ;
2017-10-28 21:40:55 +08:00
}
2017-04-25 20:18:08 +08:00
2017-10-28 21:40:55 +08:00
void EditorSettings : : save ( ) {
//_THREAD_SAFE_METHOD_
2014-02-10 09:10:30 +08:00
2020-05-14 22:41:43 +08:00
if ( ! singleton . ptr ( ) ) {
2017-10-28 21:40:55 +08:00
return ;
2020-05-14 22:41:43 +08:00
}
2014-02-10 09:10:30 +08:00
2021-12-09 17:42:46 +08:00
if ( singleton - > config_file_path . is_empty ( ) ) {
2017-10-28 21:40:55 +08:00
ERR_PRINT ( " Cannot save EditorSettings config, no valid path " ) ;
return ;
}
2014-02-10 09:10:30 +08:00
2017-10-28 21:40:55 +08:00
Error err = ResourceSaver : : save ( singleton - > config_file_path , singleton ) ;
2016-08-17 00:25:42 +08:00
2017-10-28 21:40:55 +08:00
if ( err ! = OK ) {
2019-11-07 00:03:04 +08:00
ERR_PRINT ( " Error saving editor settings to " + singleton - > config_file_path ) ;
2018-08-24 14:47:34 +08:00
} else {
2021-10-15 20:34:11 +08:00
singleton - > changed_settings . clear ( ) ;
2018-08-24 14:47:34 +08:00
print_verbose ( " EditorSettings: Save OK! " ) ;
2017-10-28 21:40:55 +08:00
}
}
2014-02-10 09:10:30 +08:00
2021-10-15 20:34:11 +08:00
Array EditorSettings : : get_changed_settings ( ) const {
Array arr ;
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 21:40:55 +08:00
void EditorSettings : : destroy ( ) {
2020-05-14 22:41:43 +08:00
if ( ! singleton . ptr ( ) ) {
2017-10-28 21:40:55 +08:00
return ;
2020-05-14 22:41:43 +08:00
}
2017-10-28 21:40:55 +08:00
save ( ) ;
singleton = Ref < EditorSettings > ( ) ;
}
2014-02-10 09:10:30 +08:00
2017-10-28 21:40:55 +08:00
void EditorSettings : : set_optimize_save ( bool p_optimize ) {
optimize_save = p_optimize ;
}
2016-05-28 01:18:40 +08:00
2017-10-28 21:40:55 +08:00
// Properties
2016-02-22 07:15:47 +08:00
2017-10-28 21:40:55 +08:00
void EditorSettings : : set_setting ( const String & p_setting , const Variant & p_value ) {
_THREAD_SAFE_METHOD_
set ( p_setting , p_value ) ;
}
2016-02-27 23:11:40 +08:00
2017-10-28 21:40:55 +08:00
Variant EditorSettings : : get_setting ( const String & p_setting ) const {
_THREAD_SAFE_METHOD_
return get ( p_setting ) ;
}
2016-02-27 23:11:40 +08:00
2017-10-31 22:24:35 +08:00
bool EditorSettings : : has_setting ( const String & p_setting ) const {
2017-10-28 21:40:55 +08:00
_THREAD_SAFE_METHOD_
2016-02-27 23:11:40 +08:00
2017-10-31 22:24:35 +08:00
return props . has ( p_setting ) ;
2017-10-28 21:40:55 +08:00
}
2016-02-27 23:11:40 +08:00
2017-10-31 22:24:35 +08:00
void EditorSettings : : erase ( const String & p_setting ) {
2017-10-28 21:40:55 +08:00
_THREAD_SAFE_METHOD_
2017-10-31 22:24:35 +08:00
props . erase ( p_setting ) ;
2016-04-12 22:45:31 +08:00
}
2017-10-31 22:24:35 +08:00
void EditorSettings : : raise_order ( const String & p_setting ) {
2017-10-28 21:40:55 +08:00
_THREAD_SAFE_METHOD_
2017-10-31 22:24:35 +08:00
ERR_FAIL_COND ( ! props . has ( p_setting ) ) ;
props [ p_setting ] . order = + + last_order ;
2014-02-10 09:10:30 +08:00
}
2018-07-20 05:58:15 +08:00
void EditorSettings : : set_restart_if_changed ( const StringName & p_setting , bool p_restart ) {
_THREAD_SAFE_METHOD_
2020-05-14 22:41:43 +08:00
if ( ! props . has ( p_setting ) ) {
2018-07-20 05:58:15 +08:00
return ;
2020-05-14 22:41:43 +08:00
}
2018-07-20 05:58:15 +08:00
props [ p_setting ] . restart_if_changed = p_restart ;
}
2018-01-09 23:52:46 +08:00
void EditorSettings : : set_initial_value ( const StringName & p_setting , const Variant & p_value , bool p_update_current ) {
2017-11-30 11:11:53 +08:00
_THREAD_SAFE_METHOD_
2020-05-14 22:41:43 +08:00
if ( ! props . has ( p_setting ) ) {
2017-11-18 04:22:27 +08:00
return ;
2020-05-14 22:41:43 +08:00
}
2018-01-08 03:39:38 +08:00
props [ p_setting ] . initial = p_value ;
props [ p_setting ] . has_default_value = true ;
2018-01-09 23:52:46 +08:00
if ( p_update_current ) {
2018-01-08 03:39:38 +08:00
set ( p_setting , p_value ) ;
}
2017-10-28 21:40:55 +08:00
}
2014-02-10 09:10:30 +08:00
2018-07-20 05:58:15 +08:00
Variant _EDITOR_DEF ( const String & p_setting , const Variant & p_default , bool p_restart_if_changed ) {
2017-10-29 05:25:28 +08:00
Variant ret = p_default ;
2018-07-20 05:58:15 +08:00
if ( EditorSettings : : get_singleton ( ) - > has_setting ( p_setting ) ) {
2017-10-29 05:25:28 +08:00
ret = EditorSettings : : get_singleton ( ) - > get ( p_setting ) ;
2018-07-20 05:58:15 +08:00
} else {
2017-11-30 11:11:53 +08:00
EditorSettings : : get_singleton ( ) - > set_manually ( p_setting , p_default ) ;
2018-07-20 05:58:15 +08:00
EditorSettings : : get_singleton ( ) - > set_restart_if_changed ( p_setting , p_restart_if_changed ) ;
}
2017-11-30 11:11:53 +08:00
2018-07-20 05:58:15 +08:00
if ( ! EditorSettings : : get_singleton ( ) - > has_default_value ( p_setting ) ) {
2017-11-21 01:34:13 +08:00
EditorSettings : : get_singleton ( ) - > set_initial_value ( p_setting , p_default ) ;
2018-07-20 05:58:15 +08:00
}
2014-02-10 09:10:30 +08:00
2017-10-29 05:25:28 +08:00
return ret ;
2017-10-28 21:40:55 +08:00
}
2014-02-10 09:10:30 +08:00
2017-10-31 22:24:35 +08:00
Variant _EDITOR_GET ( const String & p_setting ) {
2019-06-11 20:49:34 +08:00
ERR_FAIL_COND_V ( ! EditorSettings : : get_singleton ( ) - > has_setting ( p_setting ) , Variant ( ) ) ;
2017-10-31 22:24:35 +08:00
return EditorSettings : : get_singleton ( ) - > get ( p_setting ) ;
2014-02-10 09:10:30 +08:00
}
2017-10-31 22:24:35 +08:00
bool EditorSettings : : property_can_revert ( const String & p_setting ) {
2020-05-14 22:41:43 +08:00
if ( ! props . has ( p_setting ) ) {
2017-10-28 21:40:55 +08:00
return false ;
2020-05-14 22:41:43 +08:00
}
2016-08-17 04:10:53 +08:00
2020-05-14 22:41:43 +08:00
if ( ! props [ p_setting ] . has_default_value ) {
2017-11-30 11:11:53 +08:00
return false ;
2020-05-14 22:41:43 +08:00
}
2017-11-30 11:11:53 +08:00
2017-10-31 22:24:35 +08:00
return props [ p_setting ] . initial ! = props [ p_setting ] . variant ;
2017-10-28 21:40:55 +08:00
}
2016-08-17 04:10:53 +08:00
2017-10-31 22:24:35 +08:00
Variant EditorSettings : : property_get_revert ( const String & p_setting ) {
2020-05-14 22:41:43 +08:00
if ( ! props . has ( p_setting ) | | ! props [ p_setting ] . has_default_value ) {
2017-10-28 21:40:55 +08:00
return Variant ( ) ;
2020-05-14 22:41:43 +08:00
}
2017-10-28 21:40:55 +08:00
2017-10-31 22:24:35 +08:00
return props [ p_setting ] . initial ;
2016-08-17 04:10:53 +08:00
}
2017-03-05 23:44:50 +08:00
void EditorSettings : : add_property_hint ( const PropertyInfo & p_hint ) {
2014-02-10 09:10:30 +08:00
_THREAD_SAFE_METHOD_
2017-03-05 23:44:50 +08:00
hints [ p_hint . name ] = p_hint ;
2014-02-10 09:10:30 +08:00
}
2021-06-09 16:47:32 +08:00
// Editor data and config directories
// EditorPaths::create() is responsible for the creation of these directories.
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-18 00:11:41 +08:00
String EditorSettings : : get_templates_dir ( ) const {
2021-05-25 08:25:11 +08:00
return EditorPaths : : get_singleton ( ) - > get_data_dir ( ) . plus_file ( " templates " ) ;
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-18 00:11:41 +08:00
}
2017-11-17 22:50:18 +08:00
String EditorSettings : : get_project_settings_dir ( ) const {
2021-06-09 16:47:32 +08:00
return EditorPaths : : get_singleton ( ) - > get_project_data_dir ( ) . plus_file ( " editor " ) ;
2017-10-28 21:40:55 +08:00
}
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-18 00:11:41 +08:00
String EditorSettings : : get_text_editor_themes_dir ( ) const {
2021-06-03 23:24:07 +08:00
return EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . plus_file ( " text_editor_themes " ) ;
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-18 00:11:41 +08:00
}
2017-10-28 21:40:55 +08:00
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-18 00:11:41 +08:00
String EditorSettings : : get_script_templates_dir ( ) const {
2021-06-03 23:24:07 +08:00
return EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . plus_file ( " script_templates " ) ;
2017-10-28 21:40:55 +08:00
}
2019-08-22 23:59:43 +08:00
String EditorSettings : : get_project_script_templates_dir ( ) const {
2021-02-18 00:44:49 +08:00
return ProjectSettings : : get_singleton ( ) - > get ( " editor/script/templates_search_path " ) ;
2019-08-22 23:59:43 +08:00
}
2019-04-09 06:18:03 +08:00
String EditorSettings : : get_feature_profiles_dir ( ) const {
2021-06-03 23:24:07 +08:00
return EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . plus_file ( " feature_profiles " ) ;
2019-04-09 06:18:03 +08:00
}
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-18 00:11:41 +08:00
// Metadata
2017-10-28 21:40:55 +08:00
void EditorSettings : : set_project_metadata ( const String & p_section , const String & p_key , Variant p_data ) {
Ref < ConfigFile > cf = memnew ( ConfigFile ) ;
2017-11-17 22:50:18 +08:00
String path = get_project_settings_dir ( ) . plus_file ( " project_metadata.cfg " ) ;
2019-08-07 18:54:30 +08:00
Error err ;
err = cf - > load ( path ) ;
2019-09-25 16:28:50 +08:00
ERR_FAIL_COND_MSG ( err ! = OK & & err ! = ERR_FILE_NOT_FOUND , " Cannot load editor settings from file ' " + path + " '. " ) ;
2017-10-28 21:40:55 +08:00
cf - > set_value ( p_section , p_key , p_data ) ;
2019-08-07 18:54:30 +08:00
err = cf - > save ( path ) ;
2019-09-25 16:28:50 +08:00
ERR_FAIL_COND_MSG ( err ! = OK , " Cannot save editor settings to file ' " + path + " '. " ) ;
2017-10-28 21:40:55 +08:00
}
2018-05-16 23:23:20 +08:00
Variant EditorSettings : : get_project_metadata ( const String & p_section , const String & p_key , Variant p_default ) const {
2017-10-28 21:40:55 +08:00
Ref < ConfigFile > cf = memnew ( ConfigFile ) ;
2017-11-17 22:50:18 +08:00
String path = get_project_settings_dir ( ) . plus_file ( " project_metadata.cfg " ) ;
2017-10-28 21:40:55 +08: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 20:02:59 +08:00
void EditorSettings : : set_favorites ( const Vector < String > & p_favorites ) {
favorites = p_favorites ;
2022-02-03 08:21:52 +08:00
String favorites_file ;
if ( Engine : : get_singleton ( ) - > is_project_manager_hint ( ) ) {
favorites_file = EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . plus_file ( " favorite_dirs " ) ;
} else {
favorites_file = get_project_settings_dir ( ) . plus_file ( " favorites " ) ;
}
2022-03-23 17:08:58 +08:00
Ref < FileAccess > f = FileAccess : : open ( favorites_file , FileAccess : : WRITE ) ;
if ( f . is_valid ( ) ) {
2020-05-14 22:41:43 +08:00
for ( int i = 0 ; i < favorites . size ( ) ; i + + ) {
2018-09-18 20:02:59 +08:00
f - > store_line ( favorites [ i ] ) ;
2020-05-14 22:41:43 +08:00
}
2015-06-06 20:44:38 +08:00
}
}
2018-09-18 20:02:59 +08:00
Vector < String > EditorSettings : : get_favorites ( ) const {
return favorites ;
2015-06-06 20:44:38 +08:00
}
2017-08-13 00:52:50 +08:00
void EditorSettings : : set_recent_dirs ( const Vector < String > & p_recent_dirs ) {
recent_dirs = p_recent_dirs ;
2022-02-03 08:21:52 +08:00
String recent_dirs_file ;
if ( Engine : : get_singleton ( ) - > is_project_manager_hint ( ) ) {
recent_dirs_file = EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . plus_file ( " recent_dirs " ) ;
} else {
recent_dirs_file = get_project_settings_dir ( ) . plus_file ( " recent_dirs " ) ;
}
2022-03-23 17:08:58 +08:00
Ref < FileAccess > f = FileAccess : : open ( recent_dirs_file , FileAccess : : WRITE ) ;
if ( f . is_valid ( ) ) {
2020-05-14 22:41:43 +08:00
for ( int i = 0 ; i < recent_dirs . size ( ) ; i + + ) {
2015-06-06 20:44:38 +08:00
f - > store_line ( recent_dirs [ i ] ) ;
2020-05-14 22:41:43 +08:00
}
2015-06-06 20:44:38 +08:00
}
}
Vector < String > EditorSettings : : get_recent_dirs ( ) const {
return recent_dirs ;
}
2022-02-03 08:21:52 +08:00
void EditorSettings : : load_favorites_and_recent_dirs ( ) {
String favorites_file ;
String recent_dirs_file ;
if ( Engine : : get_singleton ( ) - > is_project_manager_hint ( ) ) {
favorites_file = EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . plus_file ( " favorite_dirs " ) ;
recent_dirs_file = EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . plus_file ( " recent_dirs " ) ;
} else {
favorites_file = get_project_settings_dir ( ) . plus_file ( " favorites " ) ;
recent_dirs_file = get_project_settings_dir ( ) . plus_file ( " recent_dirs " ) ;
}
2022-03-23 17:08:58 +08:00
Ref < FileAccess > f = FileAccess : : open ( favorites_file , FileAccess : : READ ) ;
if ( f . is_valid ( ) ) {
2015-06-06 20:44:38 +08:00
String line = f - > get_line ( ) . strip_edges ( ) ;
2021-12-09 17:42:46 +08:00
while ( ! line . is_empty ( ) ) {
2018-09-18 20:02:59 +08:00
favorites . push_back ( line ) ;
2015-06-06 20:44:38 +08:00
line = f - > get_line ( ) . strip_edges ( ) ;
}
}
2022-02-03 08:21:52 +08:00
f = FileAccess : : open ( recent_dirs_file , FileAccess : : READ ) ;
2022-03-23 17:08:58 +08:00
if ( f . is_valid ( ) ) {
2015-06-06 20:44:38 +08:00
String line = f - > get_line ( ) . strip_edges ( ) ;
2021-12-09 17:42:46 +08:00
while ( ! line . is_empty ( ) ) {
2015-06-06 20:44:38 +08:00
recent_dirs . push_back ( line ) ;
line = f - > get_line ( ) . strip_edges ( ) ;
}
}
}
2018-06-10 22:30:49 +08: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 13:59:04 +08:00
return ( icon_font_color_setting = = AUTO_COLOR & & base_color . get_luminance ( ) < 0.5 ) | | icon_font_color_setting = = LIGHT_COLOR ;
2018-06-10 22:30:49 +08:00
}
2016-04-12 22:45:31 +08:00
void EditorSettings : : list_text_editor_themes ( ) {
2021-05-27 16:22:36 +08:00
String themes = " Default,Godot 2,Custom " ;
2018-09-22 16:02:20 +08:00
2022-03-23 17:08:58 +08:00
Ref < DirAccess > d = DirAccess : : open ( get_text_editor_themes_dir ( ) ) ;
if ( d . is_valid ( ) ) {
2018-09-22 16:02:20 +08:00
List < String > custom_themes ;
2016-04-12 22:45:31 +08:00
d - > list_dir_begin ( ) ;
String file = d - > get_next ( ) ;
2021-12-09 17:42:46 +08:00
while ( ! file . is_empty ( ) ) {
2019-05-23 23:18:24 +08:00
if ( file . get_extension ( ) = = " tet " & & ! _is_default_text_editor_theme ( file . get_basename ( ) . to_lower ( ) ) ) {
2018-09-22 16:02:20 +08:00
custom_themes . push_back ( file . get_basename ( ) ) ;
2016-04-12 22:45:31 +08:00
}
file = d - > get_next ( ) ;
}
d - > list_dir_end ( ) ;
2018-09-22 16:02:20 +08:00
custom_themes . sort ( ) ;
2021-07-24 21:46:25 +08:00
for ( const String & E : custom_themes ) {
2021-07-16 11:45:57 +08:00
themes + = " , " + E ;
2018-09-22 16:02:20 +08:00
}
2016-04-12 22:45:31 +08:00
}
2017-03-05 23:44:50 +08:00
add_property_hint ( PropertyInfo ( Variant : : STRING , " text_editor/theme/color_theme " , PROPERTY_HINT_ENUM , themes ) ) ;
2016-04-12 22:45:31 +08:00
}
void EditorSettings : : load_text_editor_theme ( ) {
2019-05-23 23:18:24 +08: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 16:22:36 +08:00
if ( p_file = = " Godot 2 " ) {
_load_godot2_text_editor_theme ( ) ;
2018-01-06 19:40:43 +08:00
}
return ; // sorry for "Settings changed" console spam
2016-04-12 22:45:31 +08:00
}
2019-05-23 23:18:24 +08:00
String theme_path = get_text_editor_themes_dir ( ) . plus_file ( p_file + " .tet " ) ;
2016-04-12 22:45:31 +08:00
2017-03-05 23:44:50 +08:00
Ref < ConfigFile > cf = memnew ( ConfigFile ) ;
2016-04-12 22:45:31 +08:00
Error err = cf - > load ( theme_path ) ;
if ( err ! = OK ) {
return ;
}
List < String > keys ;
cf - > get_section_keys ( " color_theme " , & keys ) ;
2021-07-24 21:46:25 +08:00
for ( const String & key : keys ) {
2016-04-12 22:45:31 +08:00
String val = cf - > get_value ( " color_theme " , key ) ;
// don't load if it's not already there!
2021-08-16 01:14:46 +08:00
if ( has_setting ( " text_editor/theme/highlighting/ " + key ) ) {
2016-04-12 22:45:31 +08:00
// make sure it is actually a color
if ( val . is_valid_html_color ( ) & & key . find ( " color " ) > = 0 ) {
2021-08-16 01:14:46 +08:00
props [ " text_editor/theme/highlighting/ " + key ] . variant = Color : : html ( val ) ; // change manually to prevent "Settings changed" console spam
2016-04-12 22:45:31 +08:00
}
}
}
2021-07-18 05:22:52 +08:00
emit_signal ( SNAME ( " settings_changed " ) ) ;
2016-04-12 22:45:31 +08: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-03-23 17:08:58 +08:00
Ref < DirAccess > d = DirAccess : : open ( get_text_editor_themes_dir ( ) ) ;
if ( d . is_valid ( ) ) {
2017-11-18 04:48:24 +08:00
d - > copy ( p_file , get_text_editor_themes_dir ( ) . plus_file ( p_file . get_file ( ) ) ) ;
2016-04-12 22:45:31 +08:00
return true ;
}
}
return false ;
}
bool EditorSettings : : save_text_editor_theme ( ) {
2017-01-06 06:41:36 +08:00
String p_file = get ( " text_editor/theme/color_theme " ) ;
2016-04-12 22:45:31 +08:00
2019-05-23 23:18:24 +08:00
if ( _is_default_text_editor_theme ( p_file . get_file ( ) . to_lower ( ) ) ) {
2016-04-12 22:45:31 +08:00
return false ;
}
2017-11-18 04:48:24 +08:00
String theme_path = get_text_editor_themes_dir ( ) . plus_file ( p_file + " .tet " ) ;
2016-04-12 22:45:31 +08: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 23:18:24 +08:00
if ( _is_default_text_editor_theme ( p_file . get_file ( ) . to_lower ( ) . trim_suffix ( " .tet " ) ) ) {
2016-04-12 22:45:31 +08:00
return false ;
}
2017-03-05 23:44:50 +08:00
if ( _save_text_editor_theme ( p_file ) ) {
2016-04-12 22:45:31 +08:00
// 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 ( ) ;
2017-11-18 04:48:24 +08:00
if ( p_file . get_base_dir ( ) = = get_text_editor_themes_dir ( ) ) {
2017-09-25 11:26:41 +08:00
_initial_set ( " text_editor/theme/color_theme " , theme_name ) ;
2016-04-12 22:45:31 +08:00
load_text_editor_theme ( ) ;
}
return true ;
}
return false ;
}
2019-05-23 23:18:24 +08: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 23:59:43 +08:00
Vector < String > EditorSettings : : get_script_templates ( const String & p_extension , const String & p_custom_path ) {
2017-06-14 04:03:08 +08:00
Vector < String > templates ;
2019-08-22 23:59:43 +08:00
String template_dir = get_script_templates_dir ( ) ;
2020-12-15 20:04:21 +08:00
if ( ! p_custom_path . is_empty ( ) ) {
2019-08-22 23:59:43 +08:00
template_dir = p_custom_path ;
}
2022-03-23 17:08:58 +08:00
Ref < DirAccess > d = DirAccess : : open ( template_dir ) ;
if ( d . is_valid ( ) ) {
2017-06-14 04:03:08 +08:00
d - > list_dir_begin ( ) ;
String file = d - > get_next ( ) ;
2021-12-09 17:42:46 +08:00
while ( ! file . is_empty ( ) ) {
2017-06-14 04:03:08 +08: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-18 04:48:24 +08:00
String EditorSettings : : get_editor_layouts_config ( ) const {
2021-06-03 23:24:07 +08:00
return EditorPaths : : get_singleton ( ) - > get_config_dir ( ) . plus_file ( " editor_layouts.cfg " ) ;
2017-11-18 04:48:24 +08:00
}
2021-06-16 20:36:09 +08:00
float EditorSettings : : get_auto_display_scale ( ) const {
2022-04-04 17:22:51 +08:00
# if defined(OSX_ENABLED) || defined(ANDROID_ENABLED)
2021-06-16 20:36:09 +08:00
return DisplayServer : : get_singleton ( ) - > screen_get_max_scale ( ) ;
# else
const int screen = DisplayServer : : get_singleton ( ) - > window_get_current_screen ( ) ;
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 23:17:32 +08:00
// Use the smallest dimension to use a correct display scale on portrait displays.
2021-06-16 20:36:09 +08: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 21:40:55 +08:00
// Shortcuts
2014-02-10 09:10:30 +08:00
2022-04-05 18:40:26 +08:00
void EditorSettings : : add_shortcut ( const String & p_name , const Ref < Shortcut > & p_shortcut ) {
2017-03-05 23:44:50 +08:00
shortcuts [ p_name ] = p_shortcut ;
2016-06-05 08:31:29 +08:00
}
2017-05-20 23:38:03 +08:00
bool EditorSettings : : is_shortcut ( const String & p_name , const Ref < InputEvent > & p_event ) const {
2020-09-10 03:53:24 +08:00
const Map < String , Ref < Shortcut > > : : Element * E = shortcuts . find ( p_name ) ;
2019-08-15 10:57:49 +08:00
ERR_FAIL_COND_V_MSG ( ! E , false , " Unknown Shortcut: " + p_name + " . " ) ;
2016-06-05 08:31:29 +08:00
2021-08-03 23:27:45 +08:00
return E - > get ( ) - > matches_event ( p_event ) ;
2016-06-05 08:31:29 +08:00
}
2020-09-10 03:53:24 +08:00
Ref < Shortcut > EditorSettings : : get_shortcut ( const String & p_name ) const {
2020-12-07 19:31:51 +08:00
const Map < String , Ref < Shortcut > > : : Element * SC = shortcuts . find ( p_name ) ;
if ( SC ) {
return SC - > get ( ) ;
}
// 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 ;
const Map < String , List < Ref < InputEvent > > > : : Element * builtin_override = builtin_action_overrides . find ( p_name ) ;
if ( builtin_override ) {
2021-06-18 06:03:09 +08:00
sc . instantiate ( ) ;
2021-06-21 09:34:50 +08:00
sc - > set_events_list ( & builtin_override - > get ( ) ) ;
2020-12-07 19:31:51 +08: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 ( ) ) {
2021-08-06 14:30:15 +08:00
const OrderedHashMap < String , List < Ref < InputEvent > > > : : ConstElement builtin_default = InputMap : : get_singleton ( ) - > get_builtins_with_feature_overrides_applied ( ) . find ( p_name ) ;
2020-12-07 19:31:51 +08:00
if ( builtin_default ) {
2021-06-18 06:03:09 +08:00
sc . instantiate ( ) ;
2021-06-21 09:34:50 +08:00
sc - > set_events_list ( & builtin_default . get ( ) ) ;
2020-12-07 19:31:51 +08: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 22:41:43 +08:00
}
2016-06-05 08:31:29 +08:00
2020-12-07 19:31:51 +08:00
return Ref < Shortcut > ( ) ;
2016-06-05 08:31:29 +08:00
}
void EditorSettings : : get_shortcut_list ( List < String > * r_shortcuts ) {
2021-08-10 04:13:42 +08:00
for ( const KeyValue < String , Ref < Shortcut > > & E : shortcuts ) {
r_shortcuts - > push_back ( E . key ) ;
2016-06-05 08:31:29 +08:00
}
}
2020-09-10 03:53:24 +08:00
Ref < Shortcut > ED_GET_SHORTCUT ( const String & p_path ) {
2019-06-01 21:42:22 +08:00
if ( ! EditorSettings : : get_singleton ( ) ) {
2020-04-02 07:20:12 +08:00
return nullptr ;
2019-06-01 21:42:22 +08:00
}
2020-09-10 03:53:24 +08:00
Ref < Shortcut > sc = EditorSettings : : get_singleton ( ) - > get_shortcut ( p_path ) ;
2019-08-15 10:57:49 +08:00
ERR_FAIL_COND_V_MSG ( ! sc . is_valid ( ) , sc , " Used ED_GET_SHORTCUT with invalid shortcut: " + p_path + " . " ) ;
2017-10-28 21:40:55 +08:00
return sc ;
2016-07-04 06:13:45 +08:00
}
2016-06-05 08:31:29 +08:00
2021-08-08 11:52:00 +08:00
void ED_SHORTCUT_OVERRIDE ( const String & p_path , const String & p_feature , Key p_keycode ) {
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 09:34:50 +08:00
PackedInt32Array arr ;
2021-08-14 05:31:57 +08:00
arr . push_back ( ( int32_t ) p_keycode ) ;
2021-06-21 09:34:50 +08:00
ED_SHORTCUT_OVERRIDE_ARRAY ( p_path , p_feature , arr ) ;
}
void ED_SHORTCUT_OVERRIDE_ARRAY ( const String & p_path , const String & p_feature , const PackedInt32Array & p_keycodes ) {
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 11:52:00 +08:00
// Only add the override if the OS supports the provided feature.
2021-06-21 09:34:50 +08:00
if ( ! OS : : get_singleton ( ) - > has_feature ( p_feature ) ) {
return ;
}
Array events ;
for ( int i = 0 ; i < p_keycodes . size ( ) ; i + + ) {
Key keycode = ( Key ) p_keycodes [ i ] ;
# ifdef OSX_ENABLED
// Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
2021-08-14 05:31:57 +08:00
if ( keycode = = Key : : KEY_DELETE ) {
keycode = KeyModifierMask : : CMD | Key : : BACKSPACE ;
2021-08-08 11:52:00 +08:00
}
2021-06-21 09:34:50 +08:00
# endif
Ref < InputEventKey > ie ;
2021-08-14 05:31:57 +08:00
if ( keycode ! = Key : : NONE ) {
2021-06-21 09:34:50 +08:00
ie = InputEventKey : : create_reference ( keycode ) ;
events . push_back ( ie ) ;
}
2021-08-08 11:52:00 +08:00
}
2021-06-21 09:34:50 +08:00
// Directly override the existing shortcut.
sc - > set_events ( events ) ;
2021-10-13 10:33:53 +08:00
sc - > set_meta ( " original " , events . duplicate ( true ) ) ;
2021-08-08 11:52:00 +08:00
}
2021-06-21 01:12:33 +08:00
Ref < Shortcut > ED_SHORTCUT ( const String & p_path , const String & p_name , Key p_keycode ) {
2021-06-21 09:34:50 +08:00
PackedInt32Array arr ;
2021-08-14 05:31:57 +08:00
arr . push_back ( ( int32_t ) p_keycode ) ;
2021-06-21 09:34:50 +08:00
return ED_SHORTCUT_ARRAY ( p_path , p_name , arr ) ;
}
Ref < Shortcut > ED_SHORTCUT_ARRAY ( const String & p_path , const String & p_name , const PackedInt32Array & p_keycodes ) {
Array events ;
for ( int i = 0 ; i < p_keycodes . size ( ) ; i + + ) {
Key keycode = ( Key ) p_keycodes [ i ] ;
2017-12-26 14:30:36 +08:00
# ifdef OSX_ENABLED
2021-06-21 09:34:50 +08:00
// Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
2021-08-14 05:31:57 +08:00
if ( keycode = = Key : : KEY_DELETE ) {
keycode = KeyModifierMask : : CMD | Key : : BACKSPACE ;
2021-06-21 09:34:50 +08:00
}
2017-12-26 14:30:36 +08:00
# endif
2021-06-21 09:34:50 +08:00
Ref < InputEventKey > ie ;
2021-08-14 05:31:57 +08:00
if ( keycode ! = Key : : NONE ) {
2021-06-21 09:34:50 +08:00
ie = InputEventKey : : create_reference ( keycode ) ;
events . push_back ( ie ) ;
}
2016-10-13 04:23:48 +08:00
}
2019-06-01 21:42:22 +08:00
if ( ! EditorSettings : : get_singleton ( ) ) {
2020-09-10 03:53:24 +08:00
Ref < Shortcut > sc ;
2021-06-18 06:03:09 +08:00
sc . instantiate ( ) ;
2019-06-01 21:42:22 +08:00
sc - > set_name ( p_name ) ;
2021-06-21 09:34:50 +08:00
sc - > set_events ( events ) ;
2021-10-13 10:33:53 +08:00
sc - > set_meta ( " original " , events . duplicate ( true ) ) ;
2019-06-01 21:42:22 +08:00
return sc ;
}
2020-09-10 03:53:24 +08:00
Ref < Shortcut > sc = EditorSettings : : get_singleton ( ) - > get_shortcut ( p_path ) ;
2017-10-28 21:40:55 +08:00
if ( sc . is_valid ( ) ) {
sc - > set_name ( p_name ) ; //keep name (the ones that come from disk have no name)
2021-10-13 10:33:53 +08:00
sc - > set_meta ( " original " , events . duplicate ( true ) ) ; //to compare against changes
2017-10-28 21:40:55 +08:00
return sc ;
}
2017-09-25 11:26:41 +08:00
2021-06-18 06:03:09 +08:00
sc . instantiate ( ) ;
2017-10-28 21:40:55 +08:00
sc - > set_name ( p_name ) ;
2021-06-21 09:34:50 +08:00
sc - > set_events ( events ) ;
2021-10-13 10:33:53 +08:00
sc - > set_meta ( " original " , events . duplicate ( true ) ) ; //to compare against changes
2017-10-28 21:40:55 +08:00
EditorSettings : : get_singleton ( ) - > add_shortcut ( p_path , sc ) ;
2017-09-25 11:26:41 +08:00
2017-10-28 21:40:55 +08:00
return sc ;
2017-09-25 11:26:41 +08:00
}
2020-12-07 19:31:51 +08:00
void EditorSettings : : set_builtin_action_override ( const String & p_name , const Array & p_events ) {
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 ;
2021-08-06 14:30:15 +08:00
OrderedHashMap < String , List < Ref < InputEvent > > > : : ConstElement builtin_default = InputMap : : get_singleton ( ) - > get_builtins_with_feature_overrides_applied ( ) . find ( p_name ) ;
2020-12-07 19:31:51 +08:00
if ( builtin_default ) {
List < Ref < InputEvent > > builtin_events = builtin_default . get ( ) ;
2021-08-06 14:30:15 +08: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 19:31:51 +08:00
int event_idx = 0 ;
// Check equality of each event.
2021-08-06 14:30:15 +08:00
for ( const Ref < InputEventKey > & E : builtin_key_events ) {
2021-07-16 11:45:57 +08:00
if ( ! E - > is_match ( p_events [ event_idx ] ) ) {
2020-12-07 19:31:51 +08: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 09:34:50 +08:00
shortcuts [ p_name ] - > set_events_list ( & event_list ) ;
2020-12-07 19:31:51 +08:00
}
}
const Array EditorSettings : : get_builtin_action_overrides ( const String & p_name ) const {
const Map < String , List < Ref < InputEvent > > > : : Element * AO = builtin_action_overrides . find ( p_name ) ;
if ( AO ) {
Array event_array ;
List < Ref < InputEvent > > events_list = AO - > get ( ) ;
2021-07-26 23:50:35 +08:00
for ( const Ref < InputEvent > & E : events_list ) {
2021-07-16 11:45:57 +08:00
event_array . push_back ( E ) ;
2020-12-07 19:31:51 +08:00
}
return event_array ;
}
return Array ( ) ;
}
2017-10-28 21:40:55 +08:00
void EditorSettings : : notify_changes ( ) {
_THREAD_SAFE_METHOD_
2017-09-25 11:26:41 +08:00
2017-10-28 21:40:55 +08:00
SceneTree * sml = Object : : cast_to < SceneTree > ( OS : : get_singleton ( ) - > get_main_loop ( ) ) ;
2017-09-25 11:26:41 +08:00
2017-10-28 21:40:55 +08:00
if ( ! sml ) {
return ;
}
2017-09-25 11:26:41 +08:00
2017-10-28 21:40:55 +08:00
Node * root = sml - > get_root ( ) - > get_child ( 0 ) ;
if ( ! root ) {
return ;
}
root - > propagate_notification ( NOTIFICATION_EDITOR_SETTINGS_CHANGED ) ;
2017-09-25 11:26:41 +08:00
}
2014-02-10 09:10:30 +08:00
void EditorSettings : : _bind_methods ( ) {
2017-10-06 02:34:34 +08: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-03-05 23:44:50 +08:00
ClassDB : : bind_method ( D_METHOD ( " erase " , " property " ) , & EditorSettings : : erase ) ;
2018-01-09 23:52:46 +08:00
ClassDB : : bind_method ( D_METHOD ( " set_initial_value " , " name " , " value " , " update_current " ) , & EditorSettings : : set_initial_value ) ;
2017-10-28 21:40:55 +08:00
ClassDB : : bind_method ( D_METHOD ( " property_can_revert " , " name " ) , & EditorSettings : : property_can_revert ) ;
ClassDB : : bind_method ( D_METHOD ( " property_get_revert " , " name " ) , & EditorSettings : : property_get_revert ) ;
ClassDB : : bind_method ( D_METHOD ( " add_property_info " , " info " ) , & EditorSettings : : _add_property_info_bind ) ;
2017-11-17 22:50:18 +08:00
ClassDB : : bind_method ( D_METHOD ( " get_project_settings_dir " ) , & EditorSettings : : get_project_settings_dir ) ;
2016-02-27 11:32:00 +08:00
2018-05-16 23:23:20 +08: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 20:02:59 +08:00
ClassDB : : bind_method ( D_METHOD ( " set_favorites " , " dirs " ) , & EditorSettings : : set_favorites ) ;
ClassDB : : bind_method ( D_METHOD ( " get_favorites " ) , & EditorSettings : : get_favorites ) ;
2017-03-05 23:44:50 +08: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 11:32:00 +08:00
2020-12-07 19:31:51 +08:00
ClassDB : : bind_method ( D_METHOD ( " set_builtin_action_override " , " name " , " actions_list " ) , & EditorSettings : : set_builtin_action_override ) ;
2021-10-15 20:34:11 +08: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 09:10:30 +08:00
ADD_SIGNAL ( MethodInfo ( " settings_changed " ) ) ;
2019-07-03 15:44:53 +08:00
BIND_CONSTANT ( NOTIFICATION_EDITOR_SETTINGS_CHANGED ) ;
2014-02-10 09:10:30 +08:00
}
EditorSettings : : EditorSettings ( ) {
2017-03-05 23:44:50 +08:00
last_order = 0 ;
2016-05-28 06:58:28 +08:00
2014-02-10 09:10:30 +08:00
_load_defaults ( ) ;
}
EditorSettings : : ~ EditorSettings ( ) {
}