summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/bind/core_bind.cpp3
-rw-r--r--core/class_db.cpp13
-rw-r--r--core/class_db.h1
-rw-r--r--core/image.cpp15
-rw-r--r--core/io/marshalls.cpp11
-rw-r--r--core/io/resource_format_binary.cpp3
-rw-r--r--core/math/basis.cpp4
-rw-r--r--core/math/basis.h4
-rw-r--r--core/math/expression.cpp6
-rw-r--r--core/object.cpp3
-rw-r--r--core/os/file_access.cpp32
-rw-r--r--core/os/file_access.h3
-rw-r--r--core/packed_data_container.cpp3
-rw-r--r--core/ustring.cpp18
-rw-r--r--core/ustring.h8
-rw-r--r--core/variant.cpp38
-rw-r--r--core/variant_call.cpp2
-rw-r--r--core/variant_op.cpp12
-rw-r--r--core/variant_parser.cpp3
-rw-r--r--doc/classes/Node.xml1
-rw-r--r--doc/classes/RandomNumberGenerator.xml10
-rw-r--r--doc/classes/SceneTree.xml1
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp6
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp18
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp10
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp15
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp21
-rw-r--r--drivers/gles3/shader_gles3.h4
-rw-r--r--drivers/windows/semaphore_windows.cpp3
-rw-r--r--editor/collada/collada.cpp3
-rw-r--r--editor/connections_dialog.cpp4
-rw-r--r--editor/create_dialog.cpp24
-rw-r--r--editor/create_dialog.h2
-rw-r--r--editor/doc/doc_dump.cpp6
-rw-r--r--editor/editor_feature_profile.cpp889
-rw-r--r--editor/editor_feature_profile.h142
-rw-r--r--editor/editor_inspector.cpp36
-rw-r--r--editor/editor_inspector.h4
-rw-r--r--editor/editor_node.cpp144
-rw-r--r--editor/editor_node.h7
-rw-r--r--editor/editor_properties.cpp9
-rw-r--r--editor/editor_properties_array_dict.cpp6
-rw-r--r--editor/editor_settings.cpp12
-rw-r--r--editor/editor_settings.h1
-rw-r--r--editor/editor_themes.cpp2
-rw-r--r--editor/filesystem_dock.cpp50
-rw-r--r--editor/filesystem_dock.h5
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp7
-rw-r--r--editor/output_strings.cpp3
-rw-r--r--editor/plugins/animation_tree_player_editor_plugin.cpp15
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp6
-rw-r--r--editor/plugins/baked_lightmap_editor_plugin.cpp3
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp3
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp3
-rw-r--r--editor/plugins/script_editor_plugin.cpp2
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp9
-rw-r--r--editor/plugins/sprite_editor_plugin.cpp287
-rw-r--r--editor/plugins/sprite_editor_plugin.h19
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp21
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp3
-rw-r--r--editor/project_settings_editor.cpp6
-rw-r--r--editor/property_editor.cpp21
-rw-r--r--editor/scene_tree_dock.cpp221
-rw-r--r--editor/scene_tree_dock.h5
-rwxr-xr-xeditor/translations/extract.py2
-rw-r--r--main/performance.cpp3
-rw-r--r--main/tests/test_gdscript.cpp3
-rw-r--r--modules/dds/texture_loader_dds.cpp3
-rw-r--r--modules/enet/networked_multiplayer_enet.cpp7
-rw-r--r--modules/etc/image_etc.cpp3
-rw-r--r--modules/gdscript/gdscript_editor.cpp9
-rw-r--r--modules/gdscript/gdscript_parser.cpp17
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp6
-rw-r--r--modules/mobile_vr/doc_classes/MobileVRInterface.xml11
-rw-r--r--modules/mobile_vr/mobile_vr_interface.cpp13
-rw-r--r--modules/mobile_vr/mobile_vr_interface.h3
-rw-r--r--modules/mono/editor/bindings_generator.cpp5
-rw-r--r--modules/squish/image_compress_squish.cpp3
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp3
-rw-r--r--modules/visual_script/visual_script_expression.cpp3
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp3
-rw-r--r--platform/android/java/src/org/godotengine/godot/Godot.java10
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java3
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java1
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotIO.java33
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java8
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotView.java8
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/GodotEditText.java11
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java1
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java4
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java12
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java7
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java12
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java7
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java21
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java2
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java8
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/RequestParams.java1
-rw-r--r--platform/osx/os_osx.mm6
-rw-r--r--platform/windows/os_windows.cpp4
-rw-r--r--scene/2d/tile_map.cpp6
-rw-r--r--scene/3d/light.cpp3
-rw-r--r--scene/3d/spatial.cpp3
-rw-r--r--scene/animation/animation_blend_tree.cpp1
-rw-r--r--scene/animation/animation_cache.cpp3
-rw-r--r--scene/animation/animation_tree.cpp3
-rw-r--r--scene/animation/animation_tree_player.cpp15
-rw-r--r--scene/gui/file_dialog.cpp4
-rw-r--r--scene/gui/rich_text_label.cpp3
-rw-r--r--scene/gui/tab_container.cpp44
-rw-r--r--scene/gui/tab_container.h3
-rw-r--r--scene/gui/tree.cpp7
-rw-r--r--scene/resources/resource_format_text.cpp3
-rw-r--r--scene/resources/sky.cpp8
-rw-r--r--scene/resources/sky.h2
-rw-r--r--scene/resources/surface_tool.cpp3
-rw-r--r--scene/resources/visual_shader.cpp3
-rw-r--r--servers/physics/body_sw.cpp9
-rw-r--r--servers/physics_2d/body_2d_sw.cpp9
-rw-r--r--servers/visual/shader_language.cpp6
-rw-r--r--servers/visual/visual_server_canvas.cpp22
-rw-r--r--servers/visual/visual_server_scene.cpp21
-rw-r--r--servers/visual/visual_server_viewport.cpp4
123 files changed, 2316 insertions, 376 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 98d3e77f66..ba595b9627 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -2445,7 +2445,8 @@ void _Thread::_start_func(void *ud) {
reason = "Method Not Found";
} break;
- default: {}
+ default: {
+ }
}
ERR_EXPLAIN("Could not call function '" + t->target_method.operator String() + "'' starting thread ID: " + t->get_id() + " Reason: " + reason);
diff --git a/core/class_db.cpp b/core/class_db.cpp
index f7b446707d..0c844657a4 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -312,6 +312,19 @@ void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringNa
}
}
+void ClassDB::get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) {
+
+ OBJTYPE_RLOCK;
+
+ const StringName *k = NULL;
+
+ while ((k = classes.next(k))) {
+
+ if (*k != p_class && get_parent_class(*k) == p_class)
+ p_classes->push_back(*k);
+ }
+}
+
StringName ClassDB::get_parent_class_nocheck(const StringName &p_class) {
OBJTYPE_RLOCK;
diff --git a/core/class_db.h b/core/class_db.h
index f18a7113d7..efa1a46866 100644
--- a/core/class_db.h
+++ b/core/class_db.h
@@ -214,6 +214,7 @@ public:
static void get_class_list(List<StringName> *p_classes);
static void get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
+ static void get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
static StringName get_parent_class_nocheck(const StringName &p_class);
static StringName get_parent_class(const StringName &p_class);
static bool class_exists(const StringName &p_class);
diff --git a/core/image.cpp b/core/image.cpp
index f547d7e973..90afd9f35a 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -1266,7 +1266,8 @@ void Image::shrink_x2() {
case FORMAT_RGBAH: _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break;
case FORMAT_RGBE9995: _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(r.ptr()), reinterpret_cast<uint32_t *>(w.ptr()), width, height); break;
- default: {}
+ default: {
+ }
}
}
@@ -1398,7 +1399,8 @@ Error Image::generate_mipmaps(bool p_renormalize) {
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(&wp[prev_ofs]), reinterpret_cast<uint32_t *>(&wp[ofs]), prev_w, prev_h);
break;
- default: {}
+ default: {
+ }
}
prev_ofs = ofs;
@@ -1612,7 +1614,8 @@ void Image::create(const char **p_xpm) {
if (y == (size_height - 1))
status = DONE;
} break;
- default: {}
+ default: {
+ }
}
line++;
@@ -1685,7 +1688,8 @@ bool Image::is_invisible() const {
case FORMAT_DXT5: {
detected = true;
} break;
- default: {}
+ default: {
+ }
}
return !detected;
@@ -1729,7 +1733,8 @@ Image::AlphaMode Image::detect_alpha() const {
case FORMAT_DXT5: {
detected = true;
} break;
- default: {}
+ default: {
+ }
}
if (detected)
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 363460311c..81b3829ffc 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -768,7 +768,9 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
r_variant = carray;
} break;
- default: { ERR_FAIL_V(ERR_BUG); }
+ default: {
+ ERR_FAIL_V(ERR_BUG);
+ }
}
return OK;
@@ -823,7 +825,8 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
flags |= ENCODE_FLAG_OBJECT_AS_ID;
}
} break;
- default: {} // nothing to do at this stage
+ default: {
+ } // nothing to do at this stage
}
if (buf) {
@@ -1385,7 +1388,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 4 * 4 * len;
} break;
- default: { ERR_FAIL_V(ERR_BUG); }
+ default: {
+ ERR_FAIL_V(ERR_BUG);
+ }
}
return OK;
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 42070cd132..f25abc4aab 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1725,7 +1725,8 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
get_string_index(np.get_subname(i));
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index 82b2f7006d..9fcecd1ba6 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -557,7 +557,7 @@ void Basis::set_euler_yxz(const Vector3 &p_euler) {
*this = ymat * xmat * zmat;
}
-bool Basis::is_equal_approx(const Basis &a, const Basis &b,real_t p_epsilon) const {
+bool Basis::is_equal_approx(const Basis &a, const Basis &b, real_t p_epsilon) const {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
@@ -569,7 +569,7 @@ bool Basis::is_equal_approx(const Basis &a, const Basis &b,real_t p_epsilon) con
return true;
}
-bool Basis::is_equal_approx_ratio(const Basis &a, const Basis &b,real_t p_epsilon) const {
+bool Basis::is_equal_approx_ratio(const Basis &a, const Basis &b, real_t p_epsilon) const {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
diff --git a/core/math/basis.h b/core/math/basis.h
index aa0ddb280f..75037c2c52 100644
--- a/core/math/basis.h
+++ b/core/math/basis.h
@@ -133,8 +133,8 @@ public:
return elements[0][2] * v[0] + elements[1][2] * v[1] + elements[2][2] * v[2];
}
- bool is_equal_approx(const Basis &a, const Basis &b, real_t p_epsilon=CMP_EPSILON) const;
- bool is_equal_approx_ratio(const Basis &a, const Basis &b, real_t p_epsilon=UNIT_EPSILON) const;
+ bool is_equal_approx(const Basis &a, const Basis &b, real_t p_epsilon = CMP_EPSILON) const;
+ bool is_equal_approx_ratio(const Basis &a, const Basis &b, real_t p_epsilon = UNIT_EPSILON) const;
bool operator==(const Basis &p_matrix) const;
bool operator!=(const Basis &p_matrix) const;
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 05b49f0815..133dcc7ab9 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -760,7 +760,8 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant
*r_return = String(color);
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1679,7 +1680,8 @@ Expression::ENode *Expression::_parse_expression() {
case TK_OP_BIT_OR: op = Variant::OP_BIT_OR; break;
case TK_OP_BIT_XOR: op = Variant::OP_BIT_XOR; break;
case TK_OP_BIT_INVERT: op = Variant::OP_BIT_NEGATE; break;
- default: {};
+ default: {
+ };
}
if (op == Variant::OP_MAX) { //stop appending stuff
diff --git a/core/object.cpp b/core/object.cpp
index 8b693f039c..03a11b8ca3 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1637,7 +1637,8 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) {
_clear_internal_resource_paths(d[E->get()]);
}
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 39d9f45bd7..4be1364278 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -571,10 +571,16 @@ void FileAccess::store_buffer(const uint8_t *p_src, int p_length) {
store_8(p_src[i]);
}
-Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path) {
+Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_error) {
- FileAccess *f = FileAccess::open(p_path, READ);
- ERR_FAIL_COND_V(!f, Vector<uint8_t>());
+ FileAccess *f = FileAccess::open(p_path, READ, r_error);
+ if (!f) {
+ if (r_error) { // if error requested, do not throw error
+ return Vector<uint8_t>();
+ } else {
+ ERR_FAIL_COND_V(!f, Vector<uint8_t>());
+ }
+ }
Vector<uint8_t> data;
data.resize(f->get_len());
f->get_buffer(data.ptrw(), data.size());
@@ -582,6 +588,26 @@ Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path) {
return data;
}
+String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
+
+ Error err;
+ Vector<uint8_t> array = get_file_as_array(p_path, &err);
+ if (r_error) {
+ *r_error = err;
+ }
+ if (err != OK) {
+ if (r_error) {
+ return String();
+ } else {
+ ERR_FAIL_COND_V(err != OK, String());
+ }
+ }
+
+ String ret;
+ ret.parse_utf8((const char *)array.ptr(), array.size());
+ return ret;
+}
+
String FileAccess::get_md5(const String &p_file) {
FileAccess *f = FileAccess::open(p_file, READ);
diff --git a/core/os/file_access.h b/core/os/file_access.h
index c65b75369c..9df2a5cade 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -164,7 +164,8 @@ public:
static String get_sha256(const String &p_file);
static String get_multiple_md5(const Vector<String> &p_file);
- static Vector<uint8_t> get_file_as_array(const String &p_path);
+ static Vector<uint8_t> get_file_as_array(const String &p_path, Error *r_error = NULL);
+ static String get_file_as_string(const String &p_path, Error *r_error = NULL);
template <class T>
static void make_default(AccessType p_access) {
diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp
index 99bed829c1..fa60be64a7 100644
--- a/core/packed_data_container.cpp
+++ b/core/packed_data_container.cpp
@@ -319,7 +319,8 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd
} break;
- default: {}
+ default: {
+ }
}
return OK;
diff --git a/core/ustring.cpp b/core/ustring.cpp
index ff8fcaaaaf..d60bd16921 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -3748,6 +3748,24 @@ bool String::is_valid_html_color() const {
return Color::html_is_valid(*this);
}
+bool String::is_valid_filename() const {
+
+ String stripped = strip_edges();
+ if (*this != stripped) {
+ return false;
+ }
+
+ if (stripped == String()) {
+ return false;
+ }
+
+ if (find(":") != -1 || find("/") != -1 || find("\\") != -1 || find("?") != -1 || find("*") != -1 || find("\"") != -1 || find("|") != -1 || find("%") != -1 || find("<") != -1 || find(">") != -1) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
bool String::is_valid_ip_address() const {
if (find(":") >= 0) {
diff --git a/core/ustring.h b/core/ustring.h
index 9288c1526e..85103057df 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -335,6 +335,7 @@ public:
bool is_valid_hex_number(bool p_with_prefix) const;
bool is_valid_html_color() const;
bool is_valid_ip_address() const;
+ bool is_valid_filename() const;
/**
* The constructors must not depend on other overloads
@@ -406,11 +407,18 @@ _FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) {
//tool translate
#ifdef TOOLS_ENABLED
+//gets parsed
String TTR(const String &);
+//use for c strings
+#define TTRC(m_value) m_value
+//use to avoid parsing (for use later with C strings)
+#define TTRGET(m_value) TTR(m_value)
#else
#define TTR(m_val) (String())
+#define TTRCDEF(m_value) (m_value)
+#define TTRC(m_value) (m_value)
#endif
diff --git a/core/variant.cpp b/core/variant.cpp
index 2ee2e8e293..6c54faf233 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -179,7 +179,8 @@ String Variant::get_type_name(Variant::Type p_type) {
return "PoolColorArray";
} break;
- default: {}
+ default: {
+ }
}
return "";
@@ -403,7 +404,8 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
valid_types = valid;
} break;
- default: {}
+ default: {
+ }
}
if (valid_types) {
@@ -649,7 +651,8 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
valid_types = valid;
} break;
- default: {}
+ default: {
+ }
}
if (valid_types) {
@@ -841,7 +844,8 @@ bool Variant::is_zero() const {
return reinterpret_cast<const PoolVector<Color> *>(_data._mem)->size() == 0;
} break;
- default: {}
+ default: {
+ }
}
return false;
@@ -896,7 +900,9 @@ bool Variant::is_one() const {
} break;
- default: { return !is_zero(); }
+ default: {
+ return !is_zero();
+ }
}
return false;
@@ -1039,7 +1045,8 @@ void Variant::reference(const Variant &p_variant) {
memnew_placement(_data._mem, PoolVector<Color>(*reinterpret_cast<const PoolVector<Color> *>(p_variant._data._mem)));
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1143,7 +1150,8 @@ void Variant::clear() {
reinterpret_cast<PoolVector<Color> *>(_data._mem)->~PoolVector<Color>();
} break;
- default: {} /* not needed */
+ default: {
+ } /* not needed */
}
type = NIL;
@@ -1823,7 +1831,9 @@ inline DA _convert_array_from_variant(const Variant &p_variant) {
case Variant::POOL_COLOR_ARRAY: {
return _convert_array<DA, PoolVector<Color> >(p_variant.operator PoolVector<Color>());
}
- default: { return DA(); }
+ default: {
+ return DA();
+ }
}
return DA();
@@ -2642,7 +2652,8 @@ void Variant::operator=(const Variant &p_variant) {
*reinterpret_cast<PoolVector<Color> *>(_data._mem) = *reinterpret_cast<const PoolVector<Color> *>(p_variant._data._mem);
} break;
- default: {}
+ default: {
+ }
}
}
@@ -2919,7 +2930,8 @@ uint32_t Variant::hash() const {
return hash;
} break;
- default: {}
+ default: {
+ }
}
return 0;
@@ -3167,7 +3179,8 @@ bool Variant::is_shared() const {
case OBJECT: return true;
case ARRAY: return true;
case DICTIONARY: return true;
- default: {}
+ default: {
+ }
}
return false;
@@ -3204,7 +3217,8 @@ Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) {
String err = "Too many arguments for method '" + p_method + "'";
ERR_PRINT(err.utf8().get_data());
} break;
- default: {}
+ default: {
+ }
}
return ret;
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index cbe24d4a63..143b07418e 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -294,6 +294,7 @@ struct _VariantCall {
VCALL_LOCALMEM1R(String, is_valid_hex_number);
VCALL_LOCALMEM0R(String, is_valid_html_color);
VCALL_LOCALMEM0R(String, is_valid_ip_address);
+ VCALL_LOCALMEM0R(String, is_valid_filename);
VCALL_LOCALMEM0R(String, to_int);
VCALL_LOCALMEM0R(String, to_float);
VCALL_LOCALMEM0R(String, hex_to_int);
@@ -1542,6 +1543,7 @@ void register_variant_methods() {
ADDFUNC1R(STRING, BOOL, String, is_valid_hex_number, BOOL, "with_prefix", varray(false));
ADDFUNC0R(STRING, BOOL, String, is_valid_html_color, varray());
ADDFUNC0R(STRING, BOOL, String, is_valid_ip_address, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_valid_filename, varray());
ADDFUNC0R(STRING, INT, String, to_int, varray());
ADDFUNC0R(STRING, REAL, String, to_float, varray());
ADDFUNC0R(STRING, INT, String, hex_to_int, varray());
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index b40b6ce4a6..f3c9bcaa7e 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -2781,7 +2781,8 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
return false;
}
} break;
- default: {}
+ default: {
+ }
}
if (r_valid)
@@ -2912,7 +2913,8 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
//nothing
} break;
- default: {}
+ default: {
+ }
}
}
@@ -3251,7 +3253,8 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
r_iter = idx;
return true;
} break;
- default: {}
+ default: {
+ }
}
valid = false;
@@ -3408,7 +3411,8 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
#endif
return arr->get(idx);
} break;
- default: {}
+ default: {
+ }
}
r_valid = false;
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index 0056fc75b6..6377197282 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -1948,7 +1948,8 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, " )");
} break;
- default: {}
+ default: {
+ }
}
return OK;
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index e01e3d3a20..bf32d4041a 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -146,6 +146,7 @@
</argument>
<description>
Adds the node to a group. Groups are helpers to name and organize a subset of nodes, for example "enemies" or "collectables". A node can be in any number of groups. Nodes can be assigned a group at any time, but will not be added until they are inside the scene tree (see [method is_inside_tree]). See notes in the description, and the group methods in [SceneTree].
+ [code]persistent[/code] option is used when packing node to [PackedScene] and saving to file. Non-persistent groups aren't stored.
</description>
</method>
<method name="can_process" qualifiers="const">
diff --git a/doc/classes/RandomNumberGenerator.xml b/doc/classes/RandomNumberGenerator.xml
index 07c9f2a74b..0e4ede50c0 100644
--- a/doc/classes/RandomNumberGenerator.xml
+++ b/doc/classes/RandomNumberGenerator.xml
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RandomNumberGenerator" inherits="Reference" category="Core" version="3.2">
<brief_description>
- A class for generation pseudo-random numbers.
+ A class for generating pseudo-random numbers.
</brief_description>
<description>
+ RandomNumberGenerator is a class for generating pseudo-random numbers. It currently uses PCG32. The underlying algorithm is an implementation detail. As a result, it should not be depended upon for reproducible random streams across Godot versions.
</description>
<tutorials>
</tutorials>
@@ -14,7 +15,7 @@
<return type="float">
</return>
<description>
- Generates pseudo-random float between '0.0' and '1.0'.
+ Generates pseudo-random float between '0.0' and '1.0', inclusive.
</description>
</method>
<method name="randf_range">
@@ -25,7 +26,7 @@
<argument index="1" name="to" type="float">
</argument>
<description>
- Generates pseudo-random float between [code]from[/code] and [code]to[/code].
+ Generates pseudo-random float between [code]from[/code] and [code]to[/code], inclusive.
</description>
</method>
<method name="randfn">
@@ -43,7 +44,7 @@
<return type="int">
</return>
<description>
- Generates pseudo-random 32-bit unsigned integer between '0' and '4294967295'.
+ Generates pseudo-random 32-bit unsigned integer between '0' and '4294967295', inclusive.
</description>
</method>
<method name="randi_range">
@@ -68,6 +69,7 @@
<members>
<member name="seed" type="int" setter="set_seed" getter="get_seed">
The seed used by the random number generator. A given seed will give a reproducible sequence of pseudo-random numbers.
+ [b]Note:[/b] The RNG does not have an avalanche effect, and can output similar random streams given similar seeds. Consider using a hash function to improve your seed quality if they're sourced externally.
</member>
</members>
<constants>
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index fb23ef0654..30889c385f 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -77,6 +77,7 @@
<return type="int">
</return>
<description>
+ Returns the current frame, i.e. number of frames since the application started.
</description>
</method>
<method name="get_network_connected_peers" qualifiers="const">
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index 9eb159cb31..7232d2d95a 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -943,7 +943,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
} break;
- default: {}
+ default: {
+ }
}
}
}
@@ -1032,7 +1033,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
} break;
- default: {}
+ default: {
+ }
}
}
}
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index c996078ba6..e790d5b031 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -1208,7 +1208,8 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p
} break;
- default: {}
+ default: {
+ }
}
}
}
@@ -1369,7 +1370,8 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
} break;
- default: {}
+ default: {
+ }
}
}
}
@@ -1530,7 +1532,8 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
} break;
- default: {}
+ default: {
+ }
}
}
}
@@ -1550,7 +1553,8 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste
case VS::INSTANCE_IMMEDIATE: {
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1758,7 +1762,8 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
}
} break;
- default: {}
+ default: {
+ }
}
}
@@ -2074,7 +2079,8 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado
}
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index b051c7d811..1e32d8166f 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -1557,6 +1557,10 @@ void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyIn
case ShaderLanguage::TYPE_FLOAT: {
pi.type = Variant::REAL;
+ if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
+ pi.hint = PROPERTY_HINT_RANGE;
+ pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]);
+ }
} break;
case ShaderLanguage::TYPE_VEC2: {
@@ -3737,7 +3741,8 @@ void RasterizerStorageGLES2::light_set_param(RID p_light, VS::LightParam p_param
light->version++;
light->instance_change_notify(true, false);
} break;
- default: {}
+ default: {
+ }
}
light->param[p_param] = p_value;
@@ -4880,7 +4885,8 @@ void RasterizerStorageGLES2::render_target_set_flag(RID p_render_target, RenderT
_render_target_allocate(rt);
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index d1b704e09a..56a6c51460 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1278,7 +1278,8 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1525,7 +1526,8 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo
}
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1847,7 +1849,8 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
}
} break;
- default: {}
+ default: {
+ }
}
}
@@ -3248,7 +3251,8 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
}
} break;
- default: {}
+ default: {
+ }
}
}
}
@@ -4423,7 +4427,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
break;
- default: {}
+ default: {
+ }
}
}
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 6169790163..be44d62efc 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -642,7 +642,8 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_
p_flags &= ~VS::TEXTURE_FLAG_FILTER;
}
} break;
- default: {}
+ default: {
+ }
}
#endif
@@ -2751,7 +2752,8 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[14] = v.origin.z;
gui[15] = 1;
} break;
- default: {}
+ default: {
+ }
}
}
@@ -2919,7 +2921,8 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
gui[i] = value[i].real;
}
} break;
- default: {}
+ default: {
+ }
}
}
@@ -2962,7 +2965,8 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
zeromem(data, 64);
} break;
- default: {}
+ default: {
+ }
}
}
@@ -5246,7 +5250,8 @@ void RasterizerStorageGLES3::light_set_param(RID p_light, VS::LightParam p_param
light->version++;
light->instance_change_notify(true, false);
} break;
- default: {}
+ default: {
+ }
}
light->param[p_param] = p_value;
@@ -5448,7 +5453,8 @@ AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const {
return AABB();
} break;
- default: {}
+ default: {
+ }
}
ERR_FAIL_V(AABB());
@@ -7379,7 +7385,8 @@ void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderT
_render_target_allocate(rt);
} break;
- default: {}
+ default: {
+ }
}
}
bool RasterizerStorageGLES3::render_target_was_used(RID p_render_target) {
diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index 1ed30986bf..be2c34ba07 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -289,7 +289,9 @@ private:
glUniformMatrix4fv(p_uniform, 1, false, matrix);
} break;
- default: { ERR_FAIL(); } // do nothing
+ default: {
+ ERR_FAIL();
+ } // do nothing
}
}
diff --git a/drivers/windows/semaphore_windows.cpp b/drivers/windows/semaphore_windows.cpp
index 718bb81836..55b47e45eb 100644
--- a/drivers/windows/semaphore_windows.cpp
+++ b/drivers/windows/semaphore_windows.cpp
@@ -54,7 +54,8 @@ int SemaphoreWindows::get() const {
case WAIT_TIMEOUT: {
return 0;
} break;
- default: {}
+ default: {
+ }
}
ERR_FAIL_V(-1);
diff --git a/editor/collada/collada.cpp b/editor/collada/collada.cpp
index 94e6d4ded0..94a37a3118 100644
--- a/editor/collada/collada.cpp
+++ b/editor/collada/collada.cpp
@@ -166,7 +166,8 @@ Transform Collada::Node::compute_transform(Collada &state) const {
}
} break;
- default: {}
+ default: {
+ }
}
xform = xform * xform_step;
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index f775a0a14b..045158504a 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -160,7 +160,9 @@ void ConnectDialog::_add_bind() {
case Variant::BASIS: value = Basis(); break;
case Variant::TRANSFORM: value = Transform(); break;
case Variant::COLOR: value = Color(); break;
- default: { ERR_FAIL(); } break;
+ default: {
+ ERR_FAIL();
+ } break;
}
ERR_FAIL_COND(value.get_type() == Variant::NIL);
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 364c5126d7..26bd651c2b 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -238,6 +238,26 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p
p_types[p_type] = item;
}
+bool CreateDialog::_is_class_disabled_by_feature_profile(const StringName &p_class) {
+
+ Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();
+ if (profile.is_null()) {
+ return false;
+ }
+
+ StringName class_name = p_class;
+
+ while (class_name != StringName()) {
+
+ if (profile->is_class_disabled(class_name)) {
+ return true;
+ }
+ class_name = ClassDB::get_parent_class(class_name);
+ }
+
+ return false;
+}
+
void CreateDialog::_update_search() {
search_options->clear();
@@ -264,6 +284,10 @@ void CreateDialog::_update_search() {
for (List<StringName>::Element *I = type_list.front(); I; I = I->next()) {
String type = I->get();
+
+ if (_is_class_disabled_by_feature_profile(type)) {
+ continue;
+ }
bool cpp_type = ClassDB::class_exists(type);
if (base_type == "Node" && type.begins_with("Editor"))
diff --git a/editor/create_dialog.h b/editor/create_dialog.h
index 2636e2ddef..d859f7cbe4 100644
--- a/editor/create_dialog.h
+++ b/editor/create_dialog.h
@@ -86,6 +86,8 @@ class CreateDialog : public ConfirmationDialog {
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+ bool _is_class_disabled_by_feature_profile(const StringName &p_class);
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/doc/doc_dump.cpp b/editor/doc/doc_dump.cpp
index 1a68fe5bf2..6ccf0e26ea 100644
--- a/editor/doc/doc_dump.cpp
+++ b/editor/doc/doc_dump.cpp
@@ -199,7 +199,8 @@ void DocDump::dump(const String &p_file) {
case Variant::ARRAY:
case Variant::_RID:
- default: {}
+ default: {
+ }
}
_write_string(f, 3, "<argument index=\"" + itos(i) + "\" name=\"" + _escape_string(arginfo.name) + "\" type=\"" + type_name + "\" default=\"" + _escape_string(default_arg_text) + "\">");
@@ -227,7 +228,8 @@ void DocDump::dump(const String &p_file) {
}
break;
case PROPERTY_HINT_FILE: hint = "A file:"; break;
- default: {}
+ default: {
+ }
//case PROPERTY_HINT_RESOURCE_TYPE: hint="Type: "+arginfo.hint_string; break;
};
if (hint != "")
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
new file mode 100644
index 0000000000..714df44e25
--- /dev/null
+++ b/editor/editor_feature_profile.cpp
@@ -0,0 +1,889 @@
+#include "editor_feature_profile.h"
+#include "core/io/json.h"
+#include "core/os/dir_access.h"
+#include "editor/editor_settings.h"
+#include "editor_node.h"
+#include "editor_scale.h"
+
+const char *EditorFeatureProfile::feature_names[FEATURE_MAX] = {
+ TTRC("3D Editor"),
+ TTRC("Script Editor"),
+ TTRC("Asset Library"),
+ TTRC("Scene Tree Editing"),
+ TTRC("Import Dock"),
+ TTRC("Node Dock"),
+ TTRC("Filesystem Dock")
+};
+
+const char *EditorFeatureProfile::feature_identifiers[FEATURE_MAX] = {
+ "3d",
+ "script",
+ "asset_lib",
+ "scene_tree",
+ "import_dock",
+ "node_dock",
+ "filesystem_dock"
+};
+
+void EditorFeatureProfile::set_disable_class(const StringName &p_class, bool p_disabled) {
+ if (p_disabled) {
+ disabled_classes.insert(p_class);
+ } else {
+ disabled_classes.erase(p_class);
+ }
+}
+
+bool EditorFeatureProfile::is_class_disabled(const StringName &p_class) const {
+ return disabled_classes.has(p_class);
+}
+
+void EditorFeatureProfile::set_disable_class_editor(const StringName &p_class, bool p_disabled) {
+ if (p_disabled) {
+ disabled_editors.insert(p_class);
+ } else {
+ disabled_editors.erase(p_class);
+ }
+}
+
+bool EditorFeatureProfile::is_class_editor_disabled(const StringName &p_class) const {
+ return disabled_editors.has(p_class);
+}
+
+void EditorFeatureProfile::set_disable_class_property(const StringName &p_class, const StringName &p_property, bool p_disabled) {
+
+ if (p_disabled) {
+ if (!disabled_properties.has(p_class)) {
+ disabled_properties[p_class] = Set<StringName>();
+ }
+
+ disabled_properties[p_class].insert(p_property);
+ } else {
+ ERR_FAIL_COND(!disabled_properties.has(p_class));
+ disabled_properties[p_class].erase(p_property);
+ if (disabled_properties[p_class].empty()) {
+ disabled_properties.erase(p_class);
+ }
+ }
+}
+bool EditorFeatureProfile::is_class_property_disabled(const StringName &p_class, const StringName &p_property) const {
+
+ if (!disabled_properties.has(p_class)) {
+ return false;
+ }
+
+ if (!disabled_properties[p_class].has(p_property)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool EditorFeatureProfile::has_class_properties_disabled(const StringName &p_class) const {
+ return disabled_properties.has(p_class);
+}
+
+void EditorFeatureProfile::set_disable_feature(Feature p_feature, bool p_disable) {
+
+ ERR_FAIL_INDEX(p_feature, FEATURE_MAX);
+ features_disabled[p_feature] = p_disable;
+}
+bool EditorFeatureProfile::is_feature_disabled(Feature p_feature) const {
+ ERR_FAIL_INDEX_V(p_feature, FEATURE_MAX, false);
+ return features_disabled[p_feature];
+}
+
+String EditorFeatureProfile::get_feature_name(Feature p_feature) {
+ ERR_FAIL_INDEX_V(p_feature, FEATURE_MAX, String());
+ return feature_names[p_feature];
+}
+
+Error EditorFeatureProfile::save_to_file(const String &p_path) {
+
+ Dictionary json;
+ json["type"] = "feature_profile";
+ Array dis_classes;
+ for (Set<StringName>::Element *E = disabled_classes.front(); E; E = E->next()) {
+ dis_classes.push_back(String(E->get()));
+ }
+ dis_classes.sort();
+ json["disabled_classes"] = dis_classes;
+
+ Array dis_editors;
+ for (Set<StringName>::Element *E = disabled_editors.front(); E; E = E->next()) {
+ dis_editors.push_back(String(E->get()));
+ }
+ dis_editors.sort();
+ json["disabled_editors"] = dis_editors;
+
+ Array dis_props;
+
+ for (Map<StringName, Set<StringName> >::Element *E = disabled_properties.front(); E; E = E->next()) {
+ for (Set<StringName>::Element *F = E->get().front(); F; F = F->next()) {
+ dis_props.push_back(String(E->key()) + ":" + String(F->get()));
+ }
+ }
+
+ json["disabled_properties"] = dis_props;
+
+ Array dis_features;
+ for (int i = 0; i < FEATURE_MAX; i++) {
+ if (features_disabled[i]) {
+ dis_features.push_back(feature_identifiers[i]);
+ }
+ }
+
+ json["disabled_features"] = dis_features;
+
+ FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
+
+ String text = JSON::print(json, "\t");
+ f->store_string(text);
+ f->close();
+ return OK;
+}
+
+Error EditorFeatureProfile::load_from_file(const String &p_path) {
+
+ Error err;
+ String text = FileAccess::get_file_as_string(p_path, &err);
+ if (err != OK) {
+ return err;
+ }
+
+ String err_str;
+ int err_line;
+ Variant v;
+ err = JSON::parse(text, v, err_str, err_line);
+ if (err != OK) {
+ ERR_PRINTS("Error parsing '" + p_path + "' on line " + itos(err_line) + ": " + err_str);
+ return ERR_PARSE_ERROR;
+ }
+
+ Dictionary json = v;
+
+ if (!json.has("type") || String(json["type"]) != "feature_profile") {
+ ERR_PRINTS("Error parsing '" + p_path + "', it's not a feature profile.");
+ return ERR_PARSE_ERROR;
+ }
+
+ disabled_classes.clear();
+
+ if (json.has("disabled_classes")) {
+ Array disabled_classes_arr = json["disabled_classes"];
+ for (int i = 0; i < disabled_classes_arr.size(); i++) {
+ disabled_classes.insert(disabled_classes_arr[i]);
+ }
+ }
+
+ disabled_editors.clear();
+
+ if (json.has("disabled_editors")) {
+ Array disabled_editors_arr = json["disabled_editors"];
+ for (int i = 0; i < disabled_editors_arr.size(); i++) {
+ disabled_editors.insert(disabled_editors_arr[i]);
+ }
+ }
+
+ disabled_properties.clear();
+
+ if (json.has("disabled_properties")) {
+ Array disabled_properties_arr = json["disabled_properties"];
+ for (int i = 0; i < disabled_properties_arr.size(); i++) {
+ String s = disabled_properties_arr[i];
+ set_disable_class_property(s.get_slice(":", 0), s.get_slice(":", 1), true);
+ }
+ }
+
+ if (json.has("disabled_features")) {
+
+ Array disabled_features_arr = json["disabled_features"];
+ for (int i = 0; i < FEATURE_MAX; i++) {
+ bool found = false;
+ String f = feature_identifiers[i];
+ for (int j = 0; j < disabled_features_arr.size(); j++) {
+ String fd = disabled_features_arr[j];
+ if (fd == f) {
+ found = true;
+ break;
+ }
+ }
+
+ features_disabled[i] = found;
+ }
+ }
+
+ return OK;
+}
+
+void EditorFeatureProfile::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_disable_class", "class_name", "disable"), &EditorFeatureProfile::set_disable_class);
+ ClassDB::bind_method(D_METHOD("is_class_disabled", "class_name"), &EditorFeatureProfile::is_class_disabled);
+
+ ClassDB::bind_method(D_METHOD("set_disable_class_editor", "class_name", "disable"), &EditorFeatureProfile::set_disable_class_editor);
+ ClassDB::bind_method(D_METHOD("is_class_editor_disabled", "class_name"), &EditorFeatureProfile::is_class_editor_disabled);
+
+ ClassDB::bind_method(D_METHOD("set_disable_class_property", "class_name", "property"), &EditorFeatureProfile::set_disable_class_property);
+ ClassDB::bind_method(D_METHOD("is_class_property_disabled", "class_name"), &EditorFeatureProfile::is_class_property_disabled);
+
+ ClassDB::bind_method(D_METHOD("set_disable_feature", "feature", "disable"), &EditorFeatureProfile::set_disable_feature);
+ ClassDB::bind_method(D_METHOD("is_feature_disabled", "feature"), &EditorFeatureProfile::is_feature_disabled);
+
+ ClassDB::bind_method(D_METHOD("get_feature_name", "feature"), &EditorFeatureProfile::_get_feature_name);
+
+ ClassDB::bind_method(D_METHOD("save_to_file", "path"), &EditorFeatureProfile::save_to_file);
+ ClassDB::bind_method(D_METHOD("load_from_file", "path"), &EditorFeatureProfile::load_from_file);
+
+ BIND_ENUM_CONSTANT(FEATURE_3D);
+ BIND_ENUM_CONSTANT(FEATURE_SCRIPT);
+ BIND_ENUM_CONSTANT(FEATURE_ASSET_LIB);
+ BIND_ENUM_CONSTANT(FEATURE_SCENE_TREE);
+ BIND_ENUM_CONSTANT(FEATURE_IMPORT_DOCK);
+ BIND_ENUM_CONSTANT(FEATURE_NODE_DOCK);
+ BIND_ENUM_CONSTANT(FEATURE_FILESYSTEM_DOCK);
+ BIND_ENUM_CONSTANT(FEATURE_MAX);
+}
+
+EditorFeatureProfile::EditorFeatureProfile() {
+
+ for (int i = 0; i < FEATURE_MAX; i++) {
+ features_disabled[i] = false;
+ }
+}
+
+//////////////////////////
+
+void EditorFeatureProfileManager::_notification(int p_what) {
+ if (p_what == NOTIFICATION_READY) {
+
+ current_profile = EDITOR_GET("_default_feature_profile");
+ if (current_profile != String()) {
+ current.instance();
+ Error err = current->load_from_file(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(current_profile + ".profile"));
+ if (err != OK) {
+ ERR_PRINTS("Error loading default feature profile: " + current_profile);
+ current_profile = String();
+ current.unref();
+ }
+ }
+ _update_profile_list(current_profile);
+ }
+}
+
+String EditorFeatureProfileManager::_get_selected_profile() {
+ int idx = profile_list->get_selected();
+ if (idx < 0) {
+ return String();
+ }
+
+ return profile_list->get_item_metadata(idx);
+}
+
+void EditorFeatureProfileManager::_update_profile_list(const String &p_select_profile) {
+
+ String selected_profile;
+ if (p_select_profile == String()) { //default, keep
+ if (profile_list->get_selected() >= 0) {
+ selected_profile = profile_list->get_item_metadata(profile_list->get_selected());
+ if (!FileAccess::exists(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(selected_profile + ".profile"))) {
+ selected_profile = String(); //does not exist
+ }
+ }
+ } else {
+ selected_profile = p_select_profile;
+ }
+
+ Vector<String> profiles;
+ DirAccessRef d = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
+ ERR_FAIL_COND(!d);
+ d->list_dir_begin();
+ while (true) {
+ String f = d->get_next();
+ if (f == String()) {
+ break;
+ }
+
+ if (!d->current_is_dir()) {
+ int last_pos = f.find_last(".profile");
+ if (last_pos != -1) {
+ profiles.push_back(f.substr(0, last_pos));
+ }
+ }
+ }
+
+ profiles.sort();
+
+ profile_list->clear();
+
+ for (int i = 0; i < profiles.size(); i++) {
+ String name = profiles[i];
+
+ if (i == 0 && selected_profile == String()) {
+ selected_profile = name;
+ }
+
+ if (name == current_profile) {
+ name += " (current)";
+ }
+ profile_list->add_item(name);
+ int index = profile_list->get_item_count() - 1;
+ profile_list->set_item_metadata(index, profiles[i]);
+ if (profiles[i] == selected_profile) {
+ profile_list->select(index);
+ }
+ }
+
+ profile_actions[PROFILE_CLEAR]->set_disabled(current_profile == String());
+ profile_actions[PROFILE_ERASE]->set_disabled(selected_profile == String());
+ profile_actions[PROFILE_EXPORT]->set_disabled(selected_profile == String());
+ profile_actions[PROFILE_SET]->set_disabled(selected_profile == String());
+
+ current_profile_name->set_text(current_profile);
+
+ _update_selected_profile();
+}
+
+void EditorFeatureProfileManager::_profile_action(int p_action) {
+
+ switch (p_action) {
+ case PROFILE_CLEAR: {
+ EditorSettings::get_singleton()->set("_default_feature_profile", "");
+ EditorSettings::get_singleton()->save();
+ current_profile = "";
+ current.unref();
+ _update_profile_list();
+ } break;
+ case PROFILE_SET: {
+
+ String selected = _get_selected_profile();
+ ERR_FAIL_COND(selected == String());
+ if (selected == current_profile) {
+ return; //nothing to do here
+ }
+ EditorSettings::get_singleton()->set("_default_feature_profile", selected);
+ EditorSettings::get_singleton()->save();
+ current_profile = selected;
+ current = edited;
+
+ _update_profile_list();
+
+ } break;
+ case PROFILE_IMPORT: {
+
+ import_profiles->popup_centered_ratio();
+ } break;
+ case PROFILE_EXPORT: {
+
+ export_profile->popup_centered_ratio();
+ export_profile->set_current_file(_get_selected_profile() + ".profile");
+ } break;
+ case PROFILE_NEW: {
+
+ new_profile_dialog->popup_centered_minsize();
+ new_profile_name->clear();
+ new_profile_name->grab_focus();
+ } break;
+ case PROFILE_ERASE: {
+ String selected = _get_selected_profile();
+ ERR_FAIL_COND(selected == String());
+
+ erase_profile_dialog->set_text(vformat(TTR("Erase profile '%s'? (no undo)"), selected));
+ erase_profile_dialog->popup_centered_minsize();
+ } break;
+ }
+}
+
+void EditorFeatureProfileManager::_erase_selected_profile() {
+
+ String selected = _get_selected_profile();
+ ERR_FAIL_COND(selected == String());
+ DirAccessRef da = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
+ ERR_FAIL_COND(!da);
+ da->remove(selected + ".profile");
+ if (selected == current_profile) {
+ _profile_action(PROFILE_CLEAR);
+ } else {
+ _update_profile_list();
+ }
+}
+
+void EditorFeatureProfileManager::_create_new_profile() {
+ String name = new_profile_name->get_text().strip_edges();
+ if (!name.is_valid_filename() || name.find(".") != -1) {
+ EditorNode::get_singleton()->show_warning(TTR("Profile must be a valid filename and must not contain '.'"));
+ return;
+ }
+ String file = EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(name + ".profile");
+ if (FileAccess::exists(file)) {
+ EditorNode::get_singleton()->show_warning(TTR("Profile with this name already exists."));
+ return;
+ }
+
+ Ref<EditorFeatureProfile> new_profile;
+ new_profile.instance();
+ new_profile->save_to_file(file);
+
+ _update_profile_list(name);
+}
+
+void EditorFeatureProfileManager::_profile_selected(int p_what) {
+
+ _update_selected_profile();
+}
+
+void EditorFeatureProfileManager::_fill_classes_from(TreeItem *p_parent, const String &p_class, const String &p_selected) {
+
+ TreeItem *class_item = class_list->create_item(p_parent);
+ class_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ class_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_class, "Node"));
+ String text = p_class;
+
+ bool disabled = edited->is_class_disabled(p_class);
+ bool disabled_editor = edited->is_class_editor_disabled(p_class);
+ bool disabled_properties = edited->has_class_properties_disabled(p_class);
+ if (disabled) {
+ class_item->set_custom_color(0, get_color("disabled_font_color", "Editor"));
+ } else if (disabled_editor && disabled_properties) {
+ text += " " + TTR("(Editor Disabled, Properties Disabled)");
+ } else if (disabled_properties) {
+ text += " " + TTR("(Properties Disabled)");
+ } else if (disabled_editor) {
+ text += " " + TTR("(Editor Disabled)");
+ }
+ class_item->set_text(0, text);
+ class_item->set_editable(0, true);
+ class_item->set_selectable(0, true);
+ class_item->set_metadata(0, p_class);
+
+ if (p_class == p_selected) {
+ class_item->select(0);
+ }
+ if (disabled) {
+ //class disabled, do nothing else (do not show further)
+ return;
+ }
+
+ class_item->set_checked(0, true); // if its not disabled, its checked
+
+ List<StringName> child_classes;
+ ClassDB::get_direct_inheriters_from_class(p_class, &child_classes);
+ child_classes.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *E = child_classes.front(); E; E = E->next()) {
+ String name = E->get();
+ if (name.begins_with("Editor") || ClassDB::get_api_type(name) != ClassDB::API_CORE) {
+ continue;
+ }
+ _fill_classes_from(class_item, name, p_selected);
+ }
+}
+
+void EditorFeatureProfileManager::_class_list_item_selected() {
+
+ if (updating_features)
+ return;
+
+ property_list->clear();
+
+ TreeItem *item = class_list->get_selected();
+ if (!item) {
+ return;
+ }
+
+ Variant md = item->get_metadata(0);
+ if (md.get_type() != Variant::STRING) {
+ return;
+ }
+
+ String class_name = md;
+
+ if (edited->is_class_disabled(class_name)) {
+ return;
+ }
+
+ updating_features = true;
+ TreeItem *root = property_list->create_item();
+ TreeItem *options = property_list->create_item(root);
+ options->set_text(0, TTR("Class Options:"));
+
+ {
+ TreeItem *option = property_list->create_item(options);
+ option->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ option->set_editable(0, true);
+ option->set_selectable(0, true);
+ option->set_checked(0, !edited->is_class_editor_disabled(class_name));
+ option->set_text(0, TTR("Enable Contextual Editor"));
+ option->set_metadata(0, CLASS_OPTION_DISABLE_EDITOR);
+ }
+
+ TreeItem *properties = property_list->create_item(root);
+ properties->set_text(0, TTR("Enabled Properties:"));
+
+ List<PropertyInfo> props;
+
+ ClassDB::get_property_list(class_name, &props, true);
+
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+
+ String name = E->get().name;
+ if (!(E->get().usage & PROPERTY_USAGE_EDITOR))
+ continue;
+ TreeItem *property = property_list->create_item(properties);
+ property->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ property->set_editable(0, true);
+ property->set_selectable(0, true);
+ property->set_checked(0, !edited->is_class_property_disabled(class_name, name));
+ property->set_text(0, name.capitalize());
+ property->set_metadata(0, name);
+ String icon_type = Variant::get_type_name(E->get().type);
+ property->set_icon(0, EditorNode::get_singleton()->get_class_icon(icon_type));
+ }
+
+ updating_features = false;
+}
+
+void EditorFeatureProfileManager::_class_list_item_edited() {
+
+ if (updating_features)
+ return;
+
+ TreeItem *item = class_list->get_edited();
+ if (!item) {
+ return;
+ }
+
+ bool checked = item->is_checked(0);
+
+ Variant md = item->get_metadata(0);
+ if (md.get_type() == Variant::STRING) {
+ String class_selected = md;
+ edited->set_disable_class(class_selected, !checked);
+ _save_and_update();
+ _update_selected_profile();
+ } else if (md.get_type() == Variant::INT) {
+ int feature_selected = md;
+ edited->set_disable_feature(EditorFeatureProfile::Feature(feature_selected), !checked);
+ _save_and_update();
+ }
+}
+
+void EditorFeatureProfileManager::_property_item_edited() {
+ if (updating_features)
+ return;
+
+ TreeItem *class_item = class_list->get_selected();
+ if (!class_item) {
+ return;
+ }
+
+ Variant md = class_item->get_metadata(0);
+ if (md.get_type() != Variant::STRING) {
+ return;
+ }
+
+ String class_name = md;
+
+ TreeItem *item = property_list->get_edited();
+ if (!item) {
+ return;
+ }
+ bool checked = item->is_checked(0);
+
+ md = item->get_metadata(0);
+ if (md.get_type() == Variant::STRING) {
+ String property_selected = md;
+ edited->set_disable_class_property(class_name, property_selected, !checked);
+ _save_and_update();
+ _update_selected_profile();
+ } else if (md.get_type() == Variant::INT) {
+ int feature_selected = md;
+ switch (feature_selected) {
+ case CLASS_OPTION_DISABLE_EDITOR: {
+ edited->set_disable_class_editor(class_name, !checked);
+ _save_and_update();
+ _update_selected_profile();
+ } break;
+ }
+ }
+}
+
+void EditorFeatureProfileManager::_update_selected_profile() {
+
+ String class_selected;
+ int feature_selected = -1;
+
+ if (class_list->get_selected()) {
+ Variant md = class_list->get_selected()->get_metadata(0);
+ if (md.get_type() == Variant::STRING) {
+ class_selected = md;
+ } else if (md.get_type() == Variant::INT) {
+ feature_selected = md;
+ }
+ }
+
+ class_list->clear();
+
+ String profile = _get_selected_profile();
+ if (profile == String()) { //nothing selected, nothing edited
+ property_list->clear();
+ edited.unref();
+ return;
+ }
+
+ if (profile == current_profile) {
+ edited = current; //reuse current profile (which is what editor uses)
+ ERR_FAIL_COND(current.is_null()); //nothing selected, current should never be null
+ } else {
+ //reload edited, if different from current
+ edited.instance();
+ Error err = edited->load_from_file(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(profile + ".profile"));
+ ERR_FAIL_COND(err != OK);
+ }
+
+ updating_features = true;
+
+ TreeItem *root = class_list->create_item();
+
+ TreeItem *features = class_list->create_item(root);
+ features->set_text(0, TTR("Enabled Features:"));
+ for (int i = 0; i < EditorFeatureProfile::FEATURE_MAX; i++) {
+
+ TreeItem *feature = class_list->create_item(features);
+ feature->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ feature->set_text(0, TTRGET(EditorFeatureProfile::get_feature_name(EditorFeatureProfile::Feature(i))));
+ feature->set_selectable(0, true);
+ feature->set_editable(0, true);
+ feature->set_metadata(0, i);
+ if (!edited->is_feature_disabled(EditorFeatureProfile::Feature(i))) {
+ feature->set_checked(0, true);
+ }
+
+ if (i == feature_selected) {
+ feature->select(0);
+ }
+ }
+
+ TreeItem *classes = class_list->create_item(root);
+ classes->set_text(0, TTR("Enabled Classes:"));
+
+ _fill_classes_from(classes, "Node", class_selected);
+ _fill_classes_from(classes, "Resource", class_selected);
+
+ updating_features = false;
+
+ _class_list_item_selected();
+}
+
+void EditorFeatureProfileManager::_import_profiles(const Vector<String> &p_paths) {
+
+ //test it first
+ for (int i = 0; i < p_paths.size(); i++) {
+ Ref<EditorFeatureProfile> profile;
+ profile.instance();
+ Error err = profile->load_from_file(p_paths[i]);
+ String basefile = p_paths[i].get_file();
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("File '%s' format is invalid, import aborted."), basefile));
+ return;
+ }
+
+ String dst_file = EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(basefile);
+
+ if (FileAccess::exists(dst_file)) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Profile '%s' already exists. Remote it first before importing, import aborted."), basefile.get_basename()));
+ return;
+ }
+ }
+
+ //do it second
+ for (int i = 0; i < p_paths.size(); i++) {
+ Ref<EditorFeatureProfile> profile;
+ profile.instance();
+ Error err = profile->load_from_file(p_paths[i]);
+ ERR_CONTINUE(err != OK);
+ String basefile = p_paths[i].get_file();
+ String dst_file = EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(basefile);
+ profile->save_to_file(dst_file);
+ }
+
+ _update_profile_list();
+}
+
+void EditorFeatureProfileManager::_export_profile(const String &p_path) {
+
+ ERR_FAIL_COND(edited.is_null());
+ Error err = edited->save_to_file(p_path);
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving profile to path: '%s'."), p_path));
+ }
+}
+
+void EditorFeatureProfileManager::_save_and_update() {
+
+ String edited_path = _get_selected_profile();
+ ERR_FAIL_COND(edited_path == String());
+ ERR_FAIL_COND(edited.is_null());
+
+ edited->save_to_file(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(edited_path + ".profile"));
+
+ if (edited == current) {
+ update_timer->start();
+ }
+}
+
+void EditorFeatureProfileManager::_emit_current_profile_changed() {
+
+ emit_signal("current_feature_profile_changed");
+}
+
+void EditorFeatureProfileManager::notify_changed() {
+ _emit_current_profile_changed();
+}
+
+Ref<EditorFeatureProfile> EditorFeatureProfileManager::get_current_profile() {
+ return current;
+}
+
+EditorFeatureProfileManager *EditorFeatureProfileManager::singleton = NULL;
+
+void EditorFeatureProfileManager::_bind_methods() {
+
+ ClassDB::bind_method("_update_selected_profile", &EditorFeatureProfileManager::_update_selected_profile);
+ ClassDB::bind_method("_profile_action", &EditorFeatureProfileManager::_profile_action);
+ ClassDB::bind_method("_create_new_profile", &EditorFeatureProfileManager::_create_new_profile);
+ ClassDB::bind_method("_profile_selected", &EditorFeatureProfileManager::_profile_selected);
+ ClassDB::bind_method("_erase_selected_profile", &EditorFeatureProfileManager::_erase_selected_profile);
+ ClassDB::bind_method("_import_profiles", &EditorFeatureProfileManager::_import_profiles);
+ ClassDB::bind_method("_export_profile", &EditorFeatureProfileManager::_export_profile);
+ ClassDB::bind_method("_class_list_item_selected", &EditorFeatureProfileManager::_class_list_item_selected);
+ ClassDB::bind_method("_class_list_item_edited", &EditorFeatureProfileManager::_class_list_item_edited);
+ ClassDB::bind_method("_property_item_edited", &EditorFeatureProfileManager::_property_item_edited);
+ ClassDB::bind_method("_emit_current_profile_changed", &EditorFeatureProfileManager::_emit_current_profile_changed);
+
+ ADD_SIGNAL(MethodInfo("current_feature_profile_changed"));
+}
+
+EditorFeatureProfileManager::EditorFeatureProfileManager() {
+
+ VBoxContainer *main_vbc = memnew(VBoxContainer);
+ add_child(main_vbc);
+
+ HBoxContainer *name_hbc = memnew(HBoxContainer);
+ current_profile_name = memnew(LineEdit);
+ name_hbc->add_child(current_profile_name);
+ current_profile_name->set_editable(false);
+ current_profile_name->set_h_size_flags(SIZE_EXPAND_FILL);
+ profile_actions[PROFILE_CLEAR] = memnew(Button(TTR("Unset")));
+ name_hbc->add_child(profile_actions[PROFILE_CLEAR]);
+ profile_actions[PROFILE_CLEAR]->set_disabled(true);
+ profile_actions[PROFILE_CLEAR]->connect("pressed", this, "_profile_action", varray(PROFILE_CLEAR));
+
+ main_vbc->add_margin_child(TTR("Current Profile"), name_hbc);
+
+ HBoxContainer *profiles_hbc = memnew(HBoxContainer);
+ profile_list = memnew(OptionButton);
+ profile_list->set_h_size_flags(SIZE_EXPAND_FILL);
+ profiles_hbc->add_child(profile_list);
+ profile_list->connect("item_selected", this, "_profile_selected");
+
+ profile_actions[PROFILE_SET] = memnew(Button(TTR("Make Current")));
+ profiles_hbc->add_child(profile_actions[PROFILE_SET]);
+ profile_actions[PROFILE_SET]->set_disabled(true);
+ profile_actions[PROFILE_SET]->connect("pressed", this, "_profile_action", varray(PROFILE_SET));
+
+ profile_actions[PROFILE_ERASE] = memnew(Button(TTR("Remove")));
+ profiles_hbc->add_child(profile_actions[PROFILE_ERASE]);
+ profile_actions[PROFILE_ERASE]->set_disabled(true);
+ profile_actions[PROFILE_ERASE]->connect("pressed", this, "_profile_action", varray(PROFILE_ERASE));
+
+ profiles_hbc->add_child(memnew(VSeparator));
+
+ profile_actions[PROFILE_NEW] = memnew(Button(TTR("New")));
+ profiles_hbc->add_child(profile_actions[PROFILE_NEW]);
+ profile_actions[PROFILE_NEW]->connect("pressed", this, "_profile_action", varray(PROFILE_NEW));
+
+ profiles_hbc->add_child(memnew(VSeparator));
+
+ profile_actions[PROFILE_IMPORT] = memnew(Button(TTR("Import")));
+ profiles_hbc->add_child(profile_actions[PROFILE_IMPORT]);
+ profile_actions[PROFILE_IMPORT]->connect("pressed", this, "_profile_action", varray(PROFILE_IMPORT));
+
+ profile_actions[PROFILE_EXPORT] = memnew(Button(TTR("Export")));
+ profiles_hbc->add_child(profile_actions[PROFILE_EXPORT]);
+ profile_actions[PROFILE_EXPORT]->set_disabled(true);
+ profile_actions[PROFILE_EXPORT]->connect("pressed", this, "_profile_action", varray(PROFILE_EXPORT));
+
+ main_vbc->add_margin_child(TTR("Available Profiles"), profiles_hbc);
+
+ h_split = memnew(HSplitContainer);
+ h_split->set_v_size_flags(SIZE_EXPAND_FILL);
+ main_vbc->add_child(h_split);
+
+ VBoxContainer *class_list_vbc = memnew(VBoxContainer);
+ h_split->add_child(class_list_vbc);
+ class_list_vbc->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ class_list = memnew(Tree);
+ class_list_vbc->add_margin_child(TTR("Enabled Classes"), class_list, true);
+ class_list->set_hide_root(true);
+ class_list->set_hide_folding(true);
+ class_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
+ class_list->connect("cell_selected", this, "_class_list_item_selected");
+ class_list->connect("item_edited", this, "_class_list_item_edited", varray(), CONNECT_DEFERRED);
+
+ VBoxContainer *property_list_vbc = memnew(VBoxContainer);
+ h_split->add_child(property_list_vbc);
+ property_list_vbc->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ property_list = memnew(Tree);
+ property_list_vbc->add_margin_child(TTR("Class Options"), property_list, true);
+ property_list->set_hide_root(true);
+ property_list->set_hide_folding(true);
+ property_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
+ property_list->connect("item_edited", this, "_property_item_edited", varray(), CONNECT_DEFERRED);
+
+ new_profile_dialog = memnew(ConfirmationDialog);
+ new_profile_dialog->set_title(TTR("New profile name:"));
+ new_profile_name = memnew(LineEdit);
+ new_profile_dialog->add_child(new_profile_name);
+ new_profile_name->set_custom_minimum_size(Size2(300 * EDSCALE, 1));
+ add_child(new_profile_dialog);
+ new_profile_dialog->connect("confirmed", this, "_create_new_profile");
+ new_profile_dialog->register_text_enter(new_profile_name);
+ new_profile_dialog->get_ok()->set_text(TTR("Create"));
+
+ erase_profile_dialog = memnew(ConfirmationDialog);
+ add_child(erase_profile_dialog);
+ erase_profile_dialog->set_title(TTR("Erase Profile"));
+ erase_profile_dialog->connect("confirmed", this, "_erase_selected_profile");
+
+ import_profiles = memnew(EditorFileDialog);
+ add_child(import_profiles);
+ import_profiles->set_mode(EditorFileDialog::MODE_OPEN_FILES);
+ import_profiles->add_filter("*.profile; Godot Feature Profile");
+ import_profiles->connect("files_selected", this, "_import_profiles");
+ import_profiles->set_title(TTR("Import Profile(s)"));
+ import_profiles->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+
+ export_profile = memnew(EditorFileDialog);
+ add_child(export_profile);
+ export_profile->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ export_profile->add_filter("*.profile; Godot Feature Profile");
+ export_profile->connect("file_selected", this, "_export_profile");
+ export_profile->set_title(TTR("Export Profile"));
+ export_profile->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+
+ set_title(TTR("Manage Editor Feature Profiles"));
+ EDITOR_DEF("_default_feature_profile", "");
+
+ update_timer = memnew(Timer);
+ update_timer->set_wait_time(1); //wait a second before updating editor
+ add_child(update_timer);
+ update_timer->connect("timeout", this, "_emit_current_profile_changed");
+ update_timer->set_one_shot(true);
+
+ updating_features = false;
+
+ singleton = this;
+}
diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h
new file mode 100644
index 0000000000..b7c2ebc1b2
--- /dev/null
+++ b/editor/editor_feature_profile.h
@@ -0,0 +1,142 @@
+#ifndef EDITOR_FEATURE_PROFILE_H
+#define EDITOR_FEATURE_PROFILE_H
+
+#include "core/os/file_access.h"
+#include "core/reference.h"
+#include "editor/editor_file_dialog.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/tree.h"
+
+class EditorFeatureProfile : public Reference {
+ GDCLASS(EditorFeatureProfile, Reference);
+
+public:
+ enum Feature {
+ FEATURE_3D,
+ FEATURE_SCRIPT,
+ FEATURE_ASSET_LIB,
+ FEATURE_SCENE_TREE,
+ FEATURE_IMPORT_DOCK,
+ FEATURE_NODE_DOCK,
+ FEATURE_FILESYSTEM_DOCK,
+ FEATURE_MAX
+ };
+
+private:
+ Set<StringName> disabled_classes;
+ Set<StringName> disabled_editors;
+ Map<StringName, Set<StringName> > disabled_properties;
+
+ bool features_disabled[FEATURE_MAX];
+ static const char *feature_names[FEATURE_MAX];
+ static const char *feature_identifiers[FEATURE_MAX];
+
+ String _get_feature_name(Feature p_feature) { return get_feature_name(p_feature); }
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_disable_class(const StringName &p_class, bool p_disabled);
+ bool is_class_disabled(const StringName &p_class) const;
+
+ void set_disable_class_editor(const StringName &p_class, bool p_disabled);
+ bool is_class_editor_disabled(const StringName &p_class) const;
+
+ void set_disable_class_property(const StringName &p_class, const StringName &p_property, bool p_disabled);
+ bool is_class_property_disabled(const StringName &p_class, const StringName &p_property) const;
+ bool has_class_properties_disabled(const StringName &p_class) const;
+
+ void set_disable_feature(Feature p_feature, bool p_disable);
+ bool is_feature_disabled(Feature p_feature) const;
+
+ Error save_to_file(const String &p_path);
+ Error load_from_file(const String &p_path);
+
+ static String get_feature_name(Feature p_feature);
+
+ EditorFeatureProfile();
+};
+
+VARIANT_ENUM_CAST(EditorFeatureProfile::Feature)
+
+class EditorFeatureProfileManager : public AcceptDialog {
+
+ GDCLASS(EditorFeatureProfileManager, AcceptDialog);
+
+ enum Action {
+ PROFILE_CLEAR,
+ PROFILE_SET,
+ PROFILE_IMPORT,
+ PROFILE_EXPORT,
+ PROFILE_NEW,
+ PROFILE_ERASE,
+ PROFILE_MAX
+ };
+
+ enum ClassOptions {
+ CLASS_OPTION_DISABLE_EDITOR
+ };
+
+ ConfirmationDialog *erase_profile_dialog;
+ ConfirmationDialog *new_profile_dialog;
+ LineEdit *new_profile_name;
+
+ LineEdit *current_profile_name;
+ OptionButton *profile_list;
+ Button *profile_actions[PROFILE_MAX];
+
+ HSplitContainer *h_split;
+
+ Tree *class_list;
+ Tree *property_list;
+
+ EditorFileDialog *import_profiles;
+ EditorFileDialog *export_profile;
+
+ void _profile_action(int p_action);
+ void _profile_selected(int p_what);
+
+ String current_profile;
+ void _update_profile_list(const String &p_select_profile = String());
+ void _update_selected_profile();
+ void _fill_classes_from(TreeItem *p_parent, const String &p_class, const String &p_selected);
+
+ Ref<EditorFeatureProfile> current;
+ Ref<EditorFeatureProfile> edited;
+
+ void _erase_selected_profile();
+ void _create_new_profile();
+ String _get_selected_profile();
+
+ void _import_profiles(const Vector<String> &p_paths);
+ void _export_profile(const String &p_path);
+
+ bool updating_features;
+
+ void _class_list_item_selected();
+ void _class_list_item_edited();
+ void _property_item_edited();
+ void _save_and_update();
+
+ Timer *update_timer;
+ void _emit_current_profile_changed();
+
+ static EditorFeatureProfileManager *singleton;
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ Ref<EditorFeatureProfile> get_current_profile();
+ void notify_changed();
+
+ static EditorFeatureProfileManager *get_singleton() { return singleton; }
+ EditorFeatureProfileManager();
+};
+
+#endif // EDITOR_FEATURE_PROFILE_H
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 60fa5ff16f..c705f9af2b 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -1370,6 +1370,30 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit
ped->added_editors.clear();
}
+bool EditorInspector::_is_property_disabled_by_feature_profile(const StringName &p_property) {
+
+ Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();
+ if (profile.is_null()) {
+ return false;
+ }
+
+ StringName class_name = object->get_class();
+
+ while (class_name != StringName()) {
+
+ if (profile->is_class_property_disabled(class_name, p_property)) {
+ return true;
+ }
+ if (profile->is_class_disabled(class_name)) {
+ //won't see properties of a disabled class
+ return true;
+ }
+ class_name = ClassDB::get_parent_class(class_name);
+ }
+
+ return false;
+}
+
void EditorInspector::update_tree() {
//to update properly if all is refreshed
@@ -1513,7 +1537,7 @@ void EditorInspector::update_tree() {
continue;
- } else if (!(p.usage & PROPERTY_USAGE_EDITOR))
+ } else if (!(p.usage & PROPERTY_USAGE_EDITOR) || _is_property_disabled_by_feature_profile(p.name))
continue;
if (p.usage & PROPERTY_USAGE_HIGH_END_GFX && VS::get_singleton()->is_low_end())
@@ -2132,6 +2156,10 @@ void EditorInspector::_node_removed(Node *p_node) {
void EditorInspector::_notification(int p_what) {
+ if (p_what == NOTIFICATION_READY) {
+ EditorFeatureProfileManager::get_singleton()->connect("current_feature_profile_changed", this, "_feature_profile_changed");
+ }
+
if (p_what == NOTIFICATION_ENTER_TREE) {
if (sub_inspector) {
@@ -2238,6 +2266,11 @@ String EditorInspector::get_object_class() const {
return object_class;
}
+void EditorInspector::_feature_profile_changed() {
+
+ update_tree();
+}
+
void EditorInspector::_bind_methods() {
ClassDB::bind_method("_property_changed", &EditorInspector::_property_changed, DEFVAL(""), DEFVAL(false));
@@ -2254,6 +2287,7 @@ void EditorInspector::_bind_methods() {
ClassDB::bind_method("_resource_selected", &EditorInspector::_resource_selected);
ClassDB::bind_method("_object_id_selected", &EditorInspector::_object_id_selected);
ClassDB::bind_method("_vscroll_changed", &EditorInspector::_vscroll_changed);
+ ClassDB::bind_method("_feature_profile_changed", &EditorInspector::_feature_profile_changed);
ClassDB::bind_method("refresh", &EditorInspector::refresh);
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index 3d22cdb9a3..494e8b5833 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -323,6 +323,10 @@ class EditorInspector : public ScrollContainer {
void _vscroll_changed(double);
+ void _feature_profile_changed();
+
+ bool _is_property_disabled_by_feature_profile(const StringName &p_property);
+
protected:
static void _bind_methods();
void _notification(int p_what);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 91e104667e..8a67002503 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -306,7 +306,14 @@ void EditorNode::_notification(int p_what) {
VisualServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport_rid(), true);
VisualServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true);
- _editor_select(EDITOR_3D);
+ feature_profile_manager->notify_changed();
+
+ if (!main_editor_buttons[EDITOR_3D]->is_visible()) { //may be hidden due to feature profile
+ _editor_select(EDITOR_2D);
+ } else {
+ _editor_select(EDITOR_3D);
+ }
+
_update_debug_options();
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
@@ -558,11 +565,14 @@ void EditorNode::_editor_select_next() {
int editor = _get_current_main_editor();
- if (editor == editor_table.size() - 1) {
- editor = 0;
- } else {
- editor++;
- }
+ do {
+ if (editor == editor_table.size() - 1) {
+ editor = 0;
+ } else {
+ editor++;
+ }
+ } while (main_editor_buttons[editor]->is_visible());
+
_editor_select(editor);
}
@@ -570,11 +580,14 @@ void EditorNode::_editor_select_prev() {
int editor = _get_current_main_editor();
- if (editor == 0) {
- editor = editor_table.size() - 1;
- } else {
- editor--;
- }
+ do {
+ if (editor == 0) {
+ editor = editor_table.size() - 1;
+ } else {
+ editor--;
+ }
+ } while (main_editor_buttons[editor]->is_visible());
+
_editor_select(editor);
}
@@ -911,7 +924,8 @@ bool EditorNode::_find_and_save_edited_subresources(Object *obj, Map<RES, bool>
ret_changed = true;
}
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1440,17 +1454,48 @@ void EditorNode::_dialog_action(String p_file) {
bool EditorNode::item_has_editor(Object *p_object) {
+ if (_is_class_editor_disabled_by_feature_profile(p_object->get_class())) {
+ return false;
+ }
+
return editor_data.get_subeditors(p_object).size() > 0;
}
void EditorNode::edit_item_resource(RES p_resource) {
edit_item(p_resource.ptr());
}
+
+bool EditorNode::_is_class_editor_disabled_by_feature_profile(const StringName &p_class) {
+
+ Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();
+ if (profile.is_null()) {
+ return false;
+ }
+
+ StringName class_name = p_class;
+
+ while (class_name != StringName()) {
+
+ if (profile->is_class_disabled(class_name)) {
+ return true;
+ }
+ if (profile->is_class_editor_disabled(class_name)) {
+ return true;
+ }
+ class_name = ClassDB::get_parent_class(class_name);
+ }
+
+ return false;
+}
+
void EditorNode::edit_item(Object *p_object) {
Vector<EditorPlugin *> sub_plugins;
if (p_object) {
+ if (_is_class_editor_disabled_by_feature_profile(p_object->get_class())) {
+ return;
+ }
sub_plugins = editor_data.get_subeditors(p_object);
}
@@ -1640,6 +1685,12 @@ void EditorNode::_edit_current() {
EditorPlugin *main_plugin = editor_data.get_editor(current_obj);
+ for (int i = 0; i < editor_table.size(); i++) {
+ if (editor_table[i] == main_plugin && !main_editor_buttons[i]->is_visible()) {
+ main_plugin = NULL; //if button is not visible, then no plugin active
+ }
+ }
+
if (main_plugin) {
// special case if use of external editor is true
@@ -1677,7 +1728,11 @@ void EditorNode::_edit_current() {
}
}
- Vector<EditorPlugin *> sub_plugins = editor_data.get_subeditors(current_obj);
+ Vector<EditorPlugin *> sub_plugins;
+
+ if (!_is_class_editor_disabled_by_feature_profile(current_obj->get_class())) {
+ sub_plugins = editor_data.get_subeditors(current_obj);
+ }
if (!sub_plugins.empty()) {
_display_top_editors(false);
@@ -1685,7 +1740,6 @@ void EditorNode::_edit_current() {
_set_top_editors(sub_plugins);
_set_editing_top_editors(current_obj);
_display_top_editors(true);
-
} else if (!editor_plugins_over->get_plugins_list().empty()) {
hide_top_editors();
@@ -2359,6 +2413,11 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
export_template_manager->popup_manager();
} break;
+ case SETTINGS_MANAGE_FEATURE_PROFILES: {
+
+ feature_profile_manager->popup_centered_ratio();
+
+ } break;
case SETTINGS_TOGGLE_FULLSCREEN: {
OS::get_singleton()->set_window_fullscreen(!OS::get_singleton()->is_window_fullscreen());
@@ -2541,10 +2600,13 @@ void EditorNode::_editor_select(int p_which) {
if (selecting || changing_scene)
return;
- selecting = true;
-
ERR_FAIL_INDEX(p_which, editor_table.size());
+ if (!main_editor_buttons[p_which]->is_visible()) //button hidden, no editor
+ return;
+
+ selecting = true;
+
for (int i = 0; i < main_editor_buttons.size(); i++) {
main_editor_buttons[i]->set_pressed(i == p_which);
}
@@ -3284,6 +3346,7 @@ void EditorNode::register_editor_types() {
ClassDB::register_class<EditorProperty>();
ClassDB::register_class<AnimationTrackEditPlugin>();
ClassDB::register_class<ScriptCreateDialog>();
+ ClassDB::register_class<EditorFeatureProfile>();
// FIXME: Is this stuff obsolete, or should it be ported to new APIs?
ClassDB::register_class<EditorScenePostImport>();
@@ -3821,7 +3884,13 @@ void EditorNode::_update_dock_slots_visibility() {
} else {
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
- if (dock_slot[i]->get_tab_count())
+ int tabs_visible = 0;
+ for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
+ if (!dock_slot[i]->get_tab_hidden(j)) {
+ tabs_visible++;
+ }
+ }
+ if (tabs_visible)
dock_slot[i]->show();
else
dock_slot[i]->hide();
@@ -4806,6 +4875,39 @@ void EditorNode::_resource_loaded(RES p_resource, const String &p_path) {
singleton->editor_folding.load_resource_folding(p_resource, p_path);
}
+void EditorNode::_feature_profile_changed() {
+
+ Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile();
+ TabContainer *import_tabs = cast_to<TabContainer>(import_dock->get_parent());
+ TabContainer *node_tabs = cast_to<TabContainer>(node_dock->get_parent());
+ TabContainer *fs_tabs = cast_to<TabContainer>(filesystem_dock->get_parent());
+ if (profile.is_valid()) {
+
+ import_tabs->set_tab_hidden(import_dock->get_index(), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_IMPORT_DOCK));
+ node_tabs->set_tab_hidden(node_dock->get_index(), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_NODE_DOCK));
+ fs_tabs->set_tab_hidden(filesystem_dock->get_index(), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_FILESYSTEM_DOCK));
+
+ main_editor_buttons[EDITOR_3D]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D));
+ main_editor_buttons[EDITOR_SCRIPT]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT));
+ main_editor_buttons[EDITOR_ASSETLIB]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB));
+ if (profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D) || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB) || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB)) {
+ _editor_select(EDITOR_2D);
+ }
+ } else {
+
+ import_tabs->set_tab_hidden(import_dock->get_index(), false);
+ node_tabs->set_tab_hidden(node_dock->get_index(), false);
+ fs_tabs->set_tab_hidden(filesystem_dock->get_index(), false);
+ import_dock->set_visible(true);
+ node_dock->set_visible(true);
+ filesystem_dock->set_visible(true);
+ main_editor_buttons[EDITOR_3D]->set_visible(true);
+ main_editor_buttons[EDITOR_ASSETLIB]->set_visible(true);
+ }
+
+ _update_dock_slots_visibility();
+}
+
void EditorNode::_bind_methods() {
ClassDB::bind_method("_menu_option", &EditorNode::_menu_option);
@@ -4884,6 +4986,7 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_video_driver_selected"), &EditorNode::_video_driver_selected);
ClassDB::bind_method(D_METHOD("_resources_changed"), &EditorNode::_resources_changed);
+ ClassDB::bind_method(D_METHOD("_feature_profile_changed"), &EditorNode::_feature_profile_changed);
ADD_SIGNAL(MethodInfo("play_pressed"));
ADD_SIGNAL(MethodInfo("pause_pressed"));
@@ -5397,8 +5500,11 @@ EditorNode::EditorNode() {
export_template_manager = memnew(ExportTemplateManager);
gui_base->add_child(export_template_manager);
+ feature_profile_manager = memnew(EditorFeatureProfileManager);
+ gui_base->add_child(feature_profile_manager);
about = memnew(EditorAbout);
gui_base->add_child(about);
+ feature_profile_manager->connect("current_feature_profile_changed", this, "_feature_profile_changed");
warning = memnew(AcceptDialog);
gui_base->add_child(warning);
@@ -5554,6 +5660,10 @@ EditorNode::EditorNode() {
}
p->add_separator();
+ p->add_item(TTR("Manage Editor Features"), SETTINGS_MANAGE_FEATURE_PROFILES);
+
+ p->add_separator();
+
p->add_item(TTR("Manage Export Templates"), SETTINGS_MANAGE_EXPORT_TEMPLATES);
// Help Menu
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 267c70c773..5ed0bd4ac3 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -38,6 +38,7 @@
#include "editor/editor_about.h"
#include "editor/editor_data.h"
#include "editor/editor_export.h"
+#include "editor/editor_feature_profile.h"
#include "editor/editor_folding.h"
#include "editor/editor_inspector.h"
#include "editor/editor_log.h"
@@ -84,7 +85,6 @@
#include "scene/gui/tool_button.h"
#include "scene/gui/tree.h"
#include "scene/gui/viewport_container.h"
-
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -175,6 +175,7 @@ private:
SETTINGS_EDITOR_DATA_FOLDER,
SETTINGS_EDITOR_CONFIG_FOLDER,
SETTINGS_MANAGE_EXPORT_TEMPLATES,
+ SETTINGS_MANAGE_FEATURE_PROFILES,
SETTINGS_PICK_MAIN_SCENE,
SETTINGS_TOGGLE_FULLSCREEN,
SETTINGS_HELP,
@@ -294,6 +295,7 @@ private:
ProjectSettingsEditor *project_settings;
EditorFileDialog *file;
ExportTemplateManager *export_template_manager;
+ EditorFeatureProfileManager *feature_profile_manager;
EditorFileDialog *file_templates;
EditorFileDialog *file_export;
EditorFileDialog *file_export_lib;
@@ -610,6 +612,9 @@ private:
void _resources_changed(const PoolVector<String> &p_resources);
+ void _feature_profile_changed();
+ bool _is_class_editor_disabled_by_feature_profile(const StringName &p_class);
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 0e8cd955b5..31f53305e2 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -2883,7 +2883,8 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
case PROPERTY_HINT_LAYERS_3D_PHYSICS:
lt = EditorPropertyLayers::LAYER_PHYSICS_3D;
break;
- default: {} //compiler could be smarter here and realize this can't happen
+ default: {
+ } //compiler could be smarter here and realize this can't happen
}
EditorPropertyLayers *editor = memnew(EditorPropertyLayers);
editor->setup(lt);
@@ -3020,7 +3021,8 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
case PROPERTY_HINT_PROPERTY_OF_BASE_TYPE: type = EditorPropertyMember::MEMBER_PROPERTY_OF_BASE_TYPE; break;
case PROPERTY_HINT_PROPERTY_OF_INSTANCE: type = EditorPropertyMember::MEMBER_PROPERTY_OF_INSTANCE; break;
case PROPERTY_HINT_PROPERTY_OF_SCRIPT: type = EditorPropertyMember::MEMBER_PROPERTY_OF_SCRIPT; break;
- default: {}
+ default: {
+ }
}
editor->setup(type, p_hint_text);
add_property_editor(p_path, editor);
@@ -3284,7 +3286,8 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
editor->setup(Variant::POOL_COLOR_ARRAY);
add_property_editor(p_path, editor);
} break;
- default: {}
+ default: {
+ }
}
return false; //can be overridden, although it will most likely be last anyway
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 0f6c6349ed..e3dc517a39 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -251,7 +251,8 @@ void EditorPropertyArray::update_property() {
case Variant::POOL_COLOR_ARRAY: {
arrtype = "PoolColorArray";
} break;
- default: {}
+ default: {
+ }
}
if (array.get_type() == Variant::NIL) {
@@ -862,7 +863,8 @@ void EditorPropertyDictionary::update_property() {
editor->setup(Variant::POOL_COLOR_ARRAY);
prop = editor;
} break;
- default: {}
+ default: {
+ }
}
if (i == amount) {
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index b9ed63c1b6..f54c51940f 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -832,6 +832,13 @@ void EditorSettings::create() {
} else {
dir->change_dir("..");
}
+
+ if (dir->change_dir("feature_profiles") != OK) {
+ dir->make_dir("feature_profiles");
+ } else {
+ dir->change_dir("..");
+ }
+
_create_script_templates(dir->get_current_dir().plus_file("script_templates"));
if (dir->change_dir("projects") != OK) {
@@ -1157,6 +1164,11 @@ String EditorSettings::get_cache_dir() const {
return cache_dir;
}
+String EditorSettings::get_feature_profiles_dir() const {
+
+ return get_settings_dir().plus_file("feature_profiles");
+}
+
// Metadata
void EditorSettings::set_project_metadata(const String &p_section, const String &p_key, Variant p_data) {
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index 1b44c15c54..43a8cbf739 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -169,6 +169,7 @@ public:
String get_text_editor_themes_dir() const;
String get_script_templates_dir() const;
String get_cache_dir() const;
+ String get_feature_profiles_dir() const;
void set_project_metadata(const String &p_section, const String &p_key, Variant p_data);
Variant get_project_metadata(const String &p_section, const String &p_key, Variant p_default) const;
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 335e3fcd29..0869f6ce77 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -204,7 +204,7 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
}
// generate thumb files with the given thumb size
- bool force_filter = !(p_thumb_size == 64 && p_thumb_size == 32); // we don't need filter with original resolution
+ bool force_filter = p_thumb_size != 64 && p_thumb_size != 32; // we don't need filter with original resolution
if (p_thumb_size >= 64) {
float scale = (float)p_thumb_size / 64.0 * EDSCALE;
for (int i = 0; i < editor_bg_thumbs_count; i++) {
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index b637148f2d..5a1383be6d 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -86,6 +86,13 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
// Create all items for the files in the subdirectory
if (display_mode == DISPLAY_MODE_TREE_ONLY) {
for (int i = 0; i < p_dir->get_file_count(); i++) {
+
+ String file_type = p_dir->get_file_type(i);
+
+ if (_is_file_type_disabled_by_feature_profile(file_type)) {
+ //if type is disabled, file wont be displayed.
+ continue;
+ }
String file_name = p_dir->get_file(i);
if (searched_string.length() > 0) {
@@ -276,6 +283,7 @@ void FileSystemDock::_notification(int p_what) {
if (initialized)
return;
initialized = true;
+ EditorFeatureProfileManager::get_singleton()->connect("current_feature_profile_changed", this, "_feature_profile_changed");
EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_fs_changed");
EditorResourcePreview::get_singleton()->connect("preview_invalidated", this, "_preview_invalidated");
@@ -520,6 +528,26 @@ void FileSystemDock::_set_file_display(bool p_active) {
_update_file_list(true);
}
+bool FileSystemDock::_is_file_type_disabled_by_feature_profile(const StringName &p_class) {
+
+ Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();
+ if (profile.is_null()) {
+ return false;
+ }
+
+ StringName class_name = p_class;
+
+ while (class_name != StringName()) {
+
+ if (profile->is_class_disabled(class_name)) {
+ return true;
+ }
+ class_name = ClassDB::get_parent_class(class_name);
+ }
+
+ return false;
+}
+
void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *matches, int p_max_items) {
if (matches->size() > p_max_items)
@@ -541,6 +569,11 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *
fi.import_broken = !p_path->get_file_import_is_valid(i);
fi.import_status = 0;
+ if (_is_file_type_disabled_by_feature_profile(fi.type)) {
+ //this type is disabled, will not appear here
+ continue;
+ }
+
matches->push_back(fi);
if (matches->size() > p_max_items)
return;
@@ -2092,6 +2125,10 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) {
}
}
+void FileSystemDock::_tree_empty_selected() {
+ tree->deselect_all();
+}
+
void FileSystemDock::_file_list_rmb_select(int p_item, const Vector2 &p_pos) {
// Right click is pressed in the file list
Vector<String> paths;
@@ -2259,6 +2296,11 @@ void FileSystemDock::_update_import_dock() {
import_dock_needs_update = false;
}
+void FileSystemDock::_feature_profile_changed() {
+
+ _update_display_mode(true);
+}
+
void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_file_list_gui_input"), &FileSystemDock::_file_list_gui_input);
@@ -2270,9 +2312,10 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_toggle_split_mode"), &FileSystemDock::_toggle_split_mode);
ClassDB::bind_method(D_METHOD("_tree_rmb_option", "option"), &FileSystemDock::_tree_rmb_option);
- ClassDB::bind_method(D_METHOD("_file_list_rmb_option", "option"), &FileSystemDock::_file_list_rmb_option);
-
ClassDB::bind_method(D_METHOD("_tree_rmb_select"), &FileSystemDock::_tree_rmb_select);
+ ClassDB::bind_method(D_METHOD("_tree_empty_selected"), &FileSystemDock::_tree_empty_selected);
+
+ ClassDB::bind_method(D_METHOD("_file_list_rmb_option", "option"), &FileSystemDock::_file_list_rmb_option);
ClassDB::bind_method(D_METHOD("_file_list_rmb_select"), &FileSystemDock::_file_list_rmb_select);
ClassDB::bind_method(D_METHOD("_file_list_rmb_pressed"), &FileSystemDock::_file_list_rmb_pressed);
@@ -2308,6 +2351,8 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_file_multi_selected"), &FileSystemDock::_file_multi_selected);
ClassDB::bind_method(D_METHOD("_update_import_dock"), &FileSystemDock::_update_import_dock);
+ ClassDB::bind_method(D_METHOD("_feature_profile_changed"), &FileSystemDock::_feature_profile_changed);
+
ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::POOL_STRING_ARRAY, "files")));
ADD_SIGNAL(MethodInfo("open"));
@@ -2405,6 +2450,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
tree->connect("item_activated", this, "_tree_activate_file");
tree->connect("multi_selected", this, "_tree_multi_selected");
tree->connect("item_rmb_selected", this, "_tree_rmb_select");
+ tree->connect("nothing_selected", this, "_tree_empty_selected");
tree->connect("gui_input", this, "_tree_gui_input");
file_list_vb = memnew(VBoxContainer);
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index cd052f9700..8b27938c8a 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -237,6 +237,7 @@ private:
void _tree_rmb_select(const Vector2 &p_pos);
void _file_list_rmb_select(int p_item, const Vector2 &p_pos);
void _file_list_rmb_pressed(const Vector2 &p_pos);
+ void _tree_empty_selected();
struct FileInfo {
String name;
@@ -268,6 +269,10 @@ private:
Vector<String> _tree_get_selected(bool remove_self_inclusion = true);
+ bool _is_file_type_disabled_by_feature_profile(const StringName &p_class);
+
+ void _feature_profile_changed();
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index e6e29df133..daa423e1d9 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -581,7 +581,9 @@ int EditorSceneImporterGLTF::_get_component_type_size(int component_type) {
case COMPONENT_TYPE_UNSIGNED_SHORT: return 2; break;
case COMPONENT_TYPE_INT: return 4; break;
case COMPONENT_TYPE_FLOAT: return 4; break;
- default: { ERR_FAIL_V(0); }
+ default: {
+ ERR_FAIL_V(0);
+ }
}
return 0;
}
@@ -631,7 +633,8 @@ Vector<double> EditorSceneImporterGLTF::_decode_accessor(GLTFState &state, int p
element_size = 16; //override for this case
}
} break;
- default: {}
+ default: {
+ }
}
Vector<double> dst_buffer;
diff --git a/editor/output_strings.cpp b/editor/output_strings.cpp
index 24b44f078f..baabaff9a8 100644
--- a/editor/output_strings.cpp
+++ b/editor/output_strings.cpp
@@ -105,7 +105,8 @@ void OutputStrings::_notification(int p_what) {
case LINE_LINK: {
} break;
- default: {}
+ default: {
+ }
}
line_ofs.y += font->get_ascent();
diff --git a/editor/plugins/animation_tree_player_editor_plugin.cpp b/editor/plugins/animation_tree_player_editor_plugin.cpp
index e2a44069d9..e21ae4834d 100644
--- a/editor/plugins/animation_tree_player_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_player_editor_plugin.cpp
@@ -200,7 +200,8 @@ void AnimationTreePlayerEditor::_edit_dialog_changed() {
if (anim_tree->transition_node_get_current(edited_node) != edit_option->get_selected())
anim_tree->transition_node_set_current(edited_node, edit_option->get_selected());
} break;
- default: {}
+ default: {
+ }
}
}
@@ -457,7 +458,8 @@ void AnimationTreePlayerEditor::_popup_edit_dialog() {
edit_dialog->set_size(Size2(150, 100));
} break;
- default: {}
+ default: {
+ }
}
}
@@ -555,7 +557,8 @@ void AnimationTreePlayerEditor::_draw_node(const StringName &p_node) {
text += "->";
break;
- default: {}
+ default: {
+ }
}
font->draw(ci, ofs + ascofs + Point2(3, 0), text, font_color);
@@ -740,7 +743,8 @@ void AnimationTreePlayerEditor::_gui_input(Ref<InputEvent> p_event) {
//open editor
//_node_edit_property(click_node);
} break;
- default: {}
+ default: {
+ }
}
}
if (mb->get_button_index() == 2) {
@@ -817,7 +821,8 @@ void AnimationTreePlayerEditor::_gui_input(Ref<InputEvent> p_event) {
anim_tree->node_set_position(click_node, new_pos);
} break;
- default: {}
+ default: {
+ }
}
click_type = CLICK_NONE;
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 6d2cdfc583..386bc1738e 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -454,7 +454,8 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) {
progress->set_max(1);
progress->set_value(0);
} break;
- default: {}
+ default: {
+ }
}
prev_status = cstatus;
}
@@ -612,7 +613,8 @@ void EditorAssetLibrary::_notification(int p_what) {
case HTTPClient::STATUS_BODY: {
load_status->set_value(0.4);
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/editor/plugins/baked_lightmap_editor_plugin.cpp b/editor/plugins/baked_lightmap_editor_plugin.cpp
index d90ff95c1f..d75f06de12 100644
--- a/editor/plugins/baked_lightmap_editor_plugin.cpp
+++ b/editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -50,7 +50,8 @@ void BakedLightmapEditorPlugin::_bake() {
case BakedLightmap::BAKE_ERROR_CANT_CREATE_IMAGE:
EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images, make sure path is writable."));
break;
- default: {}
+ default: {
+ }
}
}
}
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 89eb253afe..18586b2fe5 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -61,7 +61,8 @@ void MeshLibraryEditor::_menu_confirm() {
_import_scene_cbk(existing);
} break;
- default: {};
+ default: {
+ };
}
}
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 0dbbaf4177..af43f679fd 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -905,7 +905,8 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
bone_paint_pos = Vector2(mm->get_position().x, mm->get_position().y);
} break;
- default: {}
+ default: {
+ }
}
if (bone_painting) {
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 42aba78e96..d7d4cec07d 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1735,7 +1735,7 @@ void ScriptEditor::_update_script_names() {
String name = eh->get_class();
Ref<Texture> icon = get_icon("Help", "EditorIcons");
- String tooltip = name + TTR(" Class Reference");
+ String tooltip = vformat(TTR("%s Class Reference"), name);
_ScriptEditorItemData sd;
sd.icon = icon;
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index f48887d342..ba297539d3 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -1637,7 +1637,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
surface->update();
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1704,7 +1705,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1760,7 +1762,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp
index 3854d27567..fbc72b1396 100644
--- a/editor/plugins/sprite_editor_plugin.cpp
+++ b/editor/plugins/sprite_editor_plugin.cpp
@@ -31,7 +31,10 @@
#include "sprite_editor_plugin.h"
#include "canvas_item_editor_plugin.h"
+#include "scene/2d/collision_polygon_2d.h"
+#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/mesh_instance_2d.h"
+#include "scene/2d/polygon_2d.h"
#include "scene/gui/box_container.h"
#include "thirdparty/misc/clipper.hpp"
@@ -116,8 +119,42 @@ void SpriteEditor::_menu_option(int p_option) {
return;
}
+ selected_menu_item = (Menu)p_option;
+
switch (p_option) {
- case MENU_OPTION_CREATE_MESH_2D: {
+ case MENU_OPTION_CONVERT_TO_MESH_2D: {
+
+ debug_uv_dialog->get_ok()->set_text(TTR("Create Mesh2D"));
+ debug_uv_dialog->set_title("Mesh2D Preview");
+
+ _update_mesh_data();
+ debug_uv_dialog->popup_centered();
+ debug_uv->update();
+
+ } break;
+ case MENU_OPTION_CONVERT_TO_POLYGON_2D: {
+
+ debug_uv_dialog->get_ok()->set_text(TTR("Create Polygon2D"));
+ debug_uv_dialog->set_title("Polygon2D Preview");
+
+ _update_mesh_data();
+ debug_uv_dialog->popup_centered();
+ debug_uv->update();
+ } break;
+ case MENU_OPTION_CREATE_COLLISION_POLY_2D: {
+
+ debug_uv_dialog->get_ok()->set_text(TTR("Create CollisionPolygon2D"));
+ debug_uv_dialog->set_title("CollisionPolygon2D Preview");
+
+ _update_mesh_data();
+ debug_uv_dialog->popup_centered();
+ debug_uv->update();
+
+ } break;
+ case MENU_OPTION_CREATE_LIGHT_OCCLUDER_2D: {
+
+ debug_uv_dialog->get_ok()->set_text(TTR("Create LightOccluder2D"));
+ debug_uv_dialog->set_title("LightOccluder2D Preview");
_update_mesh_data();
debug_uv_dialog->popup_centered();
@@ -169,47 +206,107 @@ void SpriteEditor::_update_mesh_data() {
computed_indices.clear();
Size2 img_size = Vector2(image->get_width(), image->get_height());
- for (int j = 0; j < lines.size(); j++) {
- lines.write[j] = expand(lines[j], rect, epsilon);
+ for (int i = 0; i < lines.size(); i++) {
+ lines.write[i] = expand(lines[i], rect, epsilon);
+ }
+
+ if (selected_menu_item == MENU_OPTION_CONVERT_TO_MESH_2D) {
+
+ for (int j = 0; j < lines.size(); j++) {
+ int index_ofs = computed_vertices.size();
+
+ for (int i = 0; i < lines[j].size(); i++) {
+ Vector2 vtx = lines[j][i];
+ computed_uv.push_back(vtx / img_size);
- int index_ofs = computed_vertices.size();
+ vtx -= rect.position; //offset by rect position
- for (int i = 0; i < lines[j].size(); i++) {
- Vector2 vtx = lines[j][i];
- computed_uv.push_back(vtx / img_size);
+ //flip if flipped
+ if (node->is_flipped_h())
+ vtx.x = rect.size.x - vtx.x - 1.0;
+ if (node->is_flipped_v())
+ vtx.y = rect.size.y - vtx.y - 1.0;
- vtx -= rect.position; //offset by rect position
+ if (node->is_centered())
+ vtx -= rect.size / 2.0;
- //flip if flipped
- if (node->is_flipped_h())
- vtx.x = rect.size.x - vtx.x - 1.0;
- if (node->is_flipped_v())
- vtx.y = rect.size.y - vtx.y - 1.0;
+ computed_vertices.push_back(vtx);
+ }
+
+ Vector<int> poly = Geometry::triangulate_polygon(lines[j]);
- if (node->is_centered())
- vtx -= rect.size / 2.0;
+ for (int i = 0; i < poly.size(); i += 3) {
+ for (int k = 0; k < 3; k++) {
+ int idx = i + k;
+ int idxn = i + (k + 1) % 3;
+ uv_lines.push_back(lines[j][poly[idx]]);
+ uv_lines.push_back(lines[j][poly[idxn]]);
- computed_vertices.push_back(vtx);
+ computed_indices.push_back(poly[idx] + index_ofs);
+ }
+ }
}
+ }
- Vector<int> poly = Geometry::triangulate_polygon(lines[j]);
+ outline_lines.clear();
+ computed_outline_lines.clear();
- for (int i = 0; i < poly.size(); i += 3) {
- for (int k = 0; k < 3; k++) {
- int idx = i + k;
- int idxn = i + (k + 1) % 3;
- uv_lines.push_back(lines[j][poly[idx]]);
- uv_lines.push_back(lines[j][poly[idxn]]);
+ if (selected_menu_item == MENU_OPTION_CONVERT_TO_POLYGON_2D || selected_menu_item == MENU_OPTION_CREATE_COLLISION_POLY_2D || selected_menu_item == MENU_OPTION_CREATE_LIGHT_OCCLUDER_2D) {
+ outline_lines.resize(lines.size());
+ computed_outline_lines.resize(lines.size());
+ for (int pi = 0; pi < lines.size(); pi++) {
+
+ Vector<Vector2> ol;
+ Vector<Vector2> col;
+
+ ol.resize(lines[pi].size());
+ col.resize(lines[pi].size());
+
+ for (int i = 0; i < lines[pi].size(); i++) {
+ Vector2 vtx = lines[pi][i];
+
+ ol.write[i] = vtx;
+
+ vtx -= rect.position; //offset by rect position
+
+ //flip if flipped
+ if (node->is_flipped_h())
+ vtx.x = rect.size.x - vtx.x - 1.0;
+ if (node->is_flipped_v())
+ vtx.y = rect.size.y - vtx.y - 1.0;
+
+ if (node->is_centered())
+ vtx -= rect.size / 2.0;
- computed_indices.push_back(poly[idx] + index_ofs);
+ col.write[i] = vtx;
}
+
+ outline_lines.write[pi] = ol;
+ computed_outline_lines.write[pi] = col;
}
}
debug_uv->update();
}
-void SpriteEditor::_create_mesh_node() {
+void SpriteEditor::_create_node() {
+ switch (selected_menu_item) {
+ case MENU_OPTION_CONVERT_TO_MESH_2D: {
+ _convert_to_mesh_2d_node();
+ } break;
+ case MENU_OPTION_CONVERT_TO_POLYGON_2D: {
+ _convert_to_polygon_2d_node();
+ } break;
+ case MENU_OPTION_CREATE_COLLISION_POLY_2D: {
+ _create_collision_polygon_2d_node();
+ } break;
+ case MENU_OPTION_CREATE_LIGHT_OCCLUDER_2D: {
+ _create_light_occluder_2d_node();
+ } break;
+ }
+}
+
+void SpriteEditor::_convert_to_mesh_2d_node() {
if (computed_vertices.size() < 3) {
err_dialog->set_text(TTR("Invalid geometry, can't replace by mesh."));
@@ -233,6 +330,117 @@ void SpriteEditor::_create_mesh_node() {
EditorNode::get_singleton()->get_scene_tree_dock()->replace_node(node, mesh_instance);
}
+void SpriteEditor::_convert_to_polygon_2d_node() {
+ Polygon2D *polygon_2d_instance = memnew(Polygon2D);
+
+ int total_point_count = 0;
+ for (int i = 0; i < computed_outline_lines.size(); i++)
+ total_point_count += computed_outline_lines[i].size();
+
+ PoolVector2Array polygon;
+ polygon.resize(total_point_count);
+ PoolVector2Array::Write polygon_write = polygon.write();
+
+ PoolVector2Array uvs;
+ uvs.resize(total_point_count);
+ PoolVector2Array::Write uvs_write = uvs.write();
+
+ int current_point_index = 0;
+
+ Array polys;
+ polys.resize(computed_outline_lines.size());
+
+ for (int i = 0; i < computed_outline_lines.size(); i++) {
+
+ Vector<Vector2> outline = computed_outline_lines[i];
+ Vector<Vector2> uv_outline = outline_lines[i];
+
+ if (outline.size() < 3) {
+ err_dialog->set_text(TTR("Invalid geometry, can't create polygon."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
+ PoolIntArray pia;
+ pia.resize(outline.size());
+ PoolIntArray::Write pia_write = pia.write();
+
+ for (int pi = 0; pi < outline.size(); pi++) {
+ polygon_write[current_point_index] = outline[pi];
+ uvs_write[current_point_index] = uv_outline[pi];
+ pia_write[pi] = current_point_index;
+ current_point_index++;
+ }
+
+ polys[i] = pia;
+ }
+
+ polygon_2d_instance->set_uv(uvs);
+ polygon_2d_instance->set_polygon(polygon);
+ polygon_2d_instance->set_polygons(polys);
+
+ EditorNode::get_singleton()->get_scene_tree_dock()->replace_node(node, polygon_2d_instance);
+}
+
+void SpriteEditor::_create_collision_polygon_2d_node() {
+ for (int i = 0; i < computed_outline_lines.size(); i++) {
+
+ Vector<Vector2> outline = computed_outline_lines[i];
+
+ if (outline.size() < 3) {
+ err_dialog->set_text(TTR("Invalid geometry, can't create collision polygon."));
+ err_dialog->popup_centered_minsize();
+ continue;
+ }
+
+ CollisionPolygon2D *collision_polygon_2d_instance = memnew(CollisionPolygon2D);
+ collision_polygon_2d_instance->set_polygon(outline);
+
+ _add_as_sibling_or_child(node, collision_polygon_2d_instance);
+ }
+}
+
+void SpriteEditor::_create_light_occluder_2d_node() {
+ for (int i = 0; i < computed_outline_lines.size(); i++) {
+
+ Vector<Vector2> outline = computed_outline_lines[i];
+
+ if (outline.size() < 3) {
+ err_dialog->set_text(TTR("Invalid geometry, can't create light occluder."));
+ err_dialog->popup_centered_minsize();
+ continue;
+ }
+
+ Ref<OccluderPolygon2D> polygon;
+ polygon.instance();
+
+ PoolVector2Array a;
+ a.resize(outline.size());
+ PoolVector2Array::Write aw = a.write();
+ for (int io = 0; io < outline.size(); io++) {
+ aw[io] = outline[io];
+ }
+ polygon->set_polygon(a);
+
+ LightOccluder2D *light_occluder_2d_instance = memnew(LightOccluder2D);
+ light_occluder_2d_instance->set_occluder_polygon(polygon);
+
+ _add_as_sibling_or_child(node, light_occluder_2d_instance);
+ }
+}
+
+void SpriteEditor::_add_as_sibling_or_child(Node2D *p_own_node, Node2D *p_new_node) {
+ // Can't make sibling if own node is scene root
+ if (p_own_node != this->get_tree()->get_edited_scene_root()) {
+ p_own_node->get_parent()->add_child(p_new_node, true);
+ p_new_node->set_transform(p_own_node->get_transform());
+ } else {
+ p_own_node->add_child(p_new_node, true);
+ }
+
+ p_new_node->set_owner(this->get_tree()->get_edited_scene_root());
+}
+
#if 0
void SpriteEditor::_create_uv_lines() {
@@ -298,16 +506,26 @@ void SpriteEditor::_create_uv_lines() {
#endif
void SpriteEditor::_debug_uv_draw() {
- if (uv_lines.size() == 0)
- return;
-
Ref<Texture> tex = node->get_texture();
ERR_FAIL_COND(!tex.is_valid());
debug_uv->set_clip_contents(true);
debug_uv->draw_texture(tex, Point2());
debug_uv->set_custom_minimum_size(tex->get_size());
//debug_uv->draw_set_transform(Vector2(), 0, debug_uv->get_size());
- debug_uv->draw_multiline(uv_lines, Color(1.0, 0.8, 0.7));
+
+ Color color = Color(1.0, 0.8, 0.7);
+
+ if (selected_menu_item == MENU_OPTION_CONVERT_TO_MESH_2D && uv_lines.size() > 0) {
+ debug_uv->draw_multiline(uv_lines, color);
+
+ } else if ((selected_menu_item == MENU_OPTION_CONVERT_TO_POLYGON_2D || selected_menu_item == MENU_OPTION_CREATE_COLLISION_POLY_2D || selected_menu_item == MENU_OPTION_CREATE_LIGHT_OCCLUDER_2D) && outline_lines.size() > 0) {
+ for (int i = 0; i < outline_lines.size(); i++) {
+ Vector<Vector2> outline = outline_lines[i];
+
+ debug_uv->draw_polyline(outline, color);
+ debug_uv->draw_line(outline[0], outline[outline.size() - 1], color);
+ }
+ }
}
void SpriteEditor::_bind_methods() {
@@ -315,7 +533,7 @@ void SpriteEditor::_bind_methods() {
ClassDB::bind_method("_menu_option", &SpriteEditor::_menu_option);
ClassDB::bind_method("_debug_uv_draw", &SpriteEditor::_debug_uv_draw);
ClassDB::bind_method("_update_mesh_data", &SpriteEditor::_update_mesh_data);
- ClassDB::bind_method("_create_mesh_node", &SpriteEditor::_create_mesh_node);
+ ClassDB::bind_method("_create_node", &SpriteEditor::_create_node);
}
SpriteEditor::SpriteEditor() {
@@ -327,7 +545,10 @@ SpriteEditor::SpriteEditor() {
options->set_text(TTR("Sprite"));
options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Sprite", "EditorIcons"));
- options->get_popup()->add_item(TTR("Convert to 2D Mesh"), MENU_OPTION_CREATE_MESH_2D);
+ options->get_popup()->add_item(TTR("Convert to Mesh2D"), MENU_OPTION_CONVERT_TO_MESH_2D);
+ options->get_popup()->add_item(TTR("Convert to Polygon2D"), MENU_OPTION_CONVERT_TO_POLYGON_2D);
+ options->get_popup()->add_item(TTR("Create CollisionPolygon2D Sibling"), MENU_OPTION_CREATE_COLLISION_POLY_2D);
+ options->get_popup()->add_item(TTR("Create LightOccluder2D Sibling"), MENU_OPTION_CREATE_LIGHT_OCCLUDER_2D);
options->get_popup()->connect("id_pressed", this, "_menu_option");
@@ -335,7 +556,7 @@ SpriteEditor::SpriteEditor() {
add_child(err_dialog);
debug_uv_dialog = memnew(ConfirmationDialog);
- debug_uv_dialog->get_ok()->set_text(TTR("Create 2D Mesh"));
+ debug_uv_dialog->get_ok()->set_text(TTR("Create Mesh2D"));
debug_uv_dialog->set_title("Mesh 2D Preview");
VBoxContainer *vb = memnew(VBoxContainer);
debug_uv_dialog->add_child(vb);
@@ -347,7 +568,7 @@ SpriteEditor::SpriteEditor() {
debug_uv = memnew(Control);
debug_uv->connect("draw", this, "_debug_uv_draw");
scroll->add_child(debug_uv);
- debug_uv_dialog->connect("confirmed", this, "_create_mesh_node");
+ debug_uv_dialog->connect("confirmed", this, "_create_node");
HBoxContainer *hb = memnew(HBoxContainer);
hb->add_child(memnew(Label(TTR("Simplification: "))));
diff --git a/editor/plugins/sprite_editor_plugin.h b/editor/plugins/sprite_editor_plugin.h
index 7250e3df59..460f5a5707 100644
--- a/editor/plugins/sprite_editor_plugin.h
+++ b/editor/plugins/sprite_editor_plugin.h
@@ -41,9 +41,14 @@ class SpriteEditor : public Control {
GDCLASS(SpriteEditor, Control);
enum Menu {
- MENU_OPTION_CREATE_MESH_2D,
+ MENU_OPTION_CONVERT_TO_MESH_2D,
+ MENU_OPTION_CONVERT_TO_POLYGON_2D,
+ MENU_OPTION_CREATE_COLLISION_POLY_2D,
+ MENU_OPTION_CREATE_LIGHT_OCCLUDER_2D
};
+ Menu selected_menu_item;
+
Sprite *node;
MenuButton *options;
@@ -55,7 +60,8 @@ class SpriteEditor : public Control {
ConfirmationDialog *debug_uv_dialog;
Control *debug_uv;
Vector<Vector2> uv_lines;
-
+ Vector<Vector<Vector2> > outline_lines;
+ Vector<Vector<Vector2> > computed_outline_lines;
Vector<Vector2> computed_vertices;
Vector<Vector2> computed_uv;
Vector<int> computed_indices;
@@ -71,7 +77,14 @@ class SpriteEditor : public Control {
void _debug_uv_draw();
void _update_mesh_data();
- void _create_mesh_node();
+
+ void _create_node();
+ void _convert_to_mesh_2d_node();
+ void _convert_to_polygon_2d_node();
+ void _create_collision_polygon_2d_node();
+ void _create_light_occluder_2d_node();
+
+ void _add_as_sibling_or_child(Node2D *p_own_node, Node2D *p_new_node);
protected:
void _node_removed(Node *p_node);
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index 5bc1067718..03277159fc 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -770,7 +770,8 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) {
spin_z_index->show();
}
} break;
- default: {}
+ default: {
+ }
}
_update_toggle_shape_button();
workspace->update();
@@ -940,7 +941,8 @@ void TileSetEditor::_on_workspace_draw() {
spin_z_index->set_value(tileset->autotile_get_z_index(get_current_tile(), edited_shape_coord));
draw_highlight_subtile(edited_shape_coord);
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1570,7 +1572,8 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
}
}
} break;
- default: {}
+ default: {
+ }
}
}
}
@@ -1724,7 +1727,8 @@ void TileSetEditor::_on_tool_clicked(int p_tool) {
undo_redo->commit_action();
}
} break;
- default: {}
+ default: {
+ }
}
}
} else if (p_tool == TOOL_SELECT) {
@@ -1894,7 +1898,8 @@ void TileSetEditor::_select_next_tile() {
edited_shape_coord = Vector2();
_select_edited_shape_coord();
} break;
- default: {}
+ default: {
+ }
}
}
}
@@ -1931,7 +1936,8 @@ void TileSetEditor::_select_previous_tile() {
edited_shape_coord = cell_count;
_select_edited_shape_coord();
} break;
- default: {}
+ default: {
+ }
}
}
}
@@ -2668,7 +2674,8 @@ void TileSetEditor::draw_polygon_shapes() {
}
}
} break;
- default: {}
+ default: {
+ }
}
if (creating_shape) {
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index f71ff84bbe..0eeb104777 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -453,7 +453,8 @@ void VisualShaderEditor::_update_graph() {
Vector3 v = default_value;
button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3));
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index bb72c621be..2d7ad8bc04 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -294,7 +294,8 @@ void ProjectSettingsEditor::_device_input_add() {
ie = jb;
} break;
- default: {}
+ default: {
+ }
}
if (idx < 0 || idx >= events.size()) {
@@ -519,7 +520,8 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even
}
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index c45a97800c..4fa1bd74fe 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -310,7 +310,8 @@ void CustomPropertyEditor::_menu_option(int p_which) {
}
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1049,7 +1050,8 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
case Variant::POOL_COLOR_ARRAY: {
} break;
- default: {}
+ default: {
+ }
}
updating = false;
@@ -1091,7 +1093,8 @@ void CustomPropertyEditor::_file_selected(String p_file) {
emit_signal("variant_changed");
hide();
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1432,7 +1435,8 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
} break;
- default: {};
+ default: {
+ };
}
}
@@ -1699,7 +1703,8 @@ void CustomPropertyEditor::_modified(String p_string) {
case Variant::POOL_COLOR_ARRAY: {
} break;
- default: {}
+ default: {
+ }
}
updating = false;
@@ -1753,7 +1758,8 @@ void CustomPropertyEditor::_focus_enter() {
}
}
} break;
- default: {}
+ default: {
+ }
}
}
@@ -1774,7 +1780,8 @@ void CustomPropertyEditor::_focus_exit() {
value_editor[i]->select(0, 0);
}
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 7e4861cd09..85a56a904d 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -290,12 +290,18 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
switch (p_tool) {
case TOOL_BATCH_RENAME: {
+ if (!profile_allow_editing) {
+ break;
+ }
Tree *tree = scene_tree->get_scene_tree();
if (tree->is_anything_selected()) {
rename_dialog->popup_centered();
}
} break;
case TOOL_RENAME: {
+ if (!profile_allow_editing) {
+ break;
+ }
Tree *tree = scene_tree->get_scene_tree();
if (tree->is_anything_selected()) {
tree->grab_focus();
@@ -304,6 +310,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
} break;
case TOOL_NEW: {
+ if (!profile_allow_editing) {
+ break;
+ }
String preferred = "";
Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene();
@@ -319,6 +328,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
} break;
case TOOL_INSTANCE: {
+ if (!profile_allow_editing) {
+ break;
+ }
Node *scene = edited_scene;
if (!scene) {
@@ -332,10 +344,17 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
} break;
case TOOL_REPLACE: {
+ if (!profile_allow_editing) {
+ break;
+ }
create_dialog->popup_create(false, true);
} break;
case TOOL_ATTACH_SCRIPT: {
+ if (!profile_allow_script_editing) {
+ break;
+ }
+
List<Node *> selection = editor_selection->get_selected_node_list();
if (selection.empty())
break;
@@ -377,6 +396,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
} break;
case TOOL_CLEAR_SCRIPT: {
+ if (!profile_allow_script_editing) {
+ break;
+ }
+
Array selection = editor_selection->get_selected_nodes();
if (selection.empty())
@@ -404,6 +427,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
case TOOL_MOVE_UP:
case TOOL_MOVE_DOWN: {
+ if (!profile_allow_editing) {
+ break;
+ }
+
if (!scene_tree->get_selected())
break;
@@ -464,6 +491,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
} break;
case TOOL_DUPLICATE: {
+ if (!profile_allow_editing) {
+ break;
+ }
+
if (!edited_scene)
break;
@@ -533,6 +564,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
} break;
case TOOL_REPARENT: {
+ if (!profile_allow_editing) {
+ break;
+ }
+
if (!scene_tree->get_selected())
break;
@@ -559,6 +594,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
} break;
case TOOL_MAKE_ROOT: {
+ if (!profile_allow_editing) {
+ break;
+ }
+
List<Node *> nodes = editor_selection->get_selected_node_list();
ERR_FAIL_COND(nodes.size() != 1);
@@ -616,6 +655,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
} break;
case TOOL_MULTI_EDIT: {
+ if (!profile_allow_editing) {
+ break;
+ }
+
Node *root = EditorNode::get_singleton()->get_edited_scene();
if (!root)
break;
@@ -630,6 +673,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
case TOOL_ERASE: {
+ if (!profile_allow_editing) {
+ break;
+ }
+
List<Node *> remove_list = editor_selection->get_selected_node_list();
if (remove_list.empty())
@@ -649,10 +696,18 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
} break;
case TOOL_MERGE_FROM_SCENE: {
+ if (!profile_allow_editing) {
+ break;
+ }
+
EditorNode::get_singleton()->merge_from_scene();
} break;
case TOOL_NEW_SCENE_FROM: {
+ if (!profile_allow_editing) {
+ break;
+ }
+
Node *scene = editor_data->get_edited_scene_root();
if (!scene) {
@@ -704,6 +759,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
new_scene_from_dialog->set_title(TTR("Save New Scene As..."));
} break;
case TOOL_COPY_NODE_PATH: {
+
List<Node *> selection = editor_selection->get_selected_node_list();
List<Node *>::Element *e = selection.front();
if (e) {
@@ -723,6 +779,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
} break;
case TOOL_SCENE_EDITABLE_CHILDREN: {
+
+ if (!profile_allow_editing) {
+ break;
+ }
+
List<Node *> selection = editor_selection->get_selected_node_list();
List<Node *>::Element *e = selection.front();
if (e) {
@@ -740,6 +801,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
} break;
case TOOL_SCENE_USE_PLACEHOLDER: {
+
+ if (!profile_allow_editing) {
+ break;
+ }
+
List<Node *> selection = editor_selection->get_selected_node_list();
List<Node *>::Element *e = selection.front();
if (e) {
@@ -760,6 +826,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
} break;
case TOOL_SCENE_MAKE_LOCAL: {
+
+ if (!profile_allow_editing) {
+ break;
+ }
+
List<Node *> selection = editor_selection->get_selected_node_list();
List<Node *>::Element *e = selection.front();
if (e) {
@@ -782,6 +853,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
} break;
case TOOL_SCENE_OPEN: {
+
List<Node *> selection = editor_selection->get_selected_node_list();
List<Node *>::Element *e = selection.front();
if (e) {
@@ -792,9 +864,17 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
} break;
case TOOL_SCENE_CLEAR_INHERITANCE: {
+ if (!profile_allow_editing) {
+ break;
+ }
+
clear_inherit_confirm->popup_centered_minsize();
} break;
case TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM: {
+ if (!profile_allow_editing) {
+ break;
+ }
+
List<Node *> selection = editor_selection->get_selected_node_list();
List<Node *>::Element *e = selection.front();
if (e) {
@@ -807,6 +887,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
} break;
case TOOL_SCENE_OPEN_INHERITED: {
+
List<Node *> selection = editor_selection->get_selected_node_list();
List<Node *>::Element *e = selection.front();
if (e) {
@@ -894,6 +975,8 @@ void SceneTreeDock::_notification(int p_what) {
break;
first_enter = false;
+ EditorFeatureProfileManager::get_singleton()->connect("current_feature_profile_changed", this, "_feature_profile_changed");
+
CanvasItemEditorPlugin *canvas_item_plugin = Object::cast_to<CanvasItemEditorPlugin>(editor_data->get_editor("2D"));
if (canvas_item_plugin) {
canvas_item_plugin->get_canvas_item_editor()->connect("item_lock_status_changed", scene_tree, "_update_tree");
@@ -1640,7 +1723,12 @@ void SceneTreeDock::_delete_confirm() {
}
void SceneTreeDock::_update_script_button() {
- if (EditorNode::get_singleton()->get_editor_selection()->get_selection().size() == 0) {
+
+ if (!profile_allow_script_editing) {
+
+ button_create_script->hide();
+ button_clear_script->hide();
+ } else if (EditorNode::get_singleton()->get_editor_selection()->get_selection().size() == 0) {
button_create_script->hide();
button_clear_script->hide();
} else if (EditorNode::get_singleton()->get_editor_selection()->get_selection().size() == 1) {
@@ -2074,11 +2162,14 @@ void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) {
}
void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
+
if (!EditorNode::get_singleton()->get_edited_scene()) {
menu->clear();
- menu->add_icon_shortcut(get_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
- menu->add_icon_shortcut(get_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE);
+ if (profile_allow_editing) {
+ menu->add_icon_shortcut(get_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
+ menu->add_icon_shortcut(get_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE);
+ }
menu->set_size(Size2(1, 1));
menu->set_position(p_menu_pos);
@@ -2098,71 +2189,87 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
Node *selected = selection[0];
- subresources.clear();
- menu_subresources->clear();
- menu_subresources->set_size(Size2(1, 1));
- _add_children_to_popup(selection.front()->get(), 0);
- if (menu->get_item_count() > 0)
- menu->add_separator();
+ if (profile_allow_editing) {
+ subresources.clear();
+ menu_subresources->clear();
+ menu_subresources->set_size(Size2(1, 1));
+ _add_children_to_popup(selection.front()->get(), 0);
+ if (menu->get_item_count() > 0)
+ menu->add_separator();
- menu->add_icon_shortcut(get_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
- menu->add_icon_shortcut(get_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE);
- menu->add_separator();
+ menu->add_icon_shortcut(get_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
+ menu->add_icon_shortcut(get_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE);
+ menu->add_separator();
+ }
existing_script = selected->get_script();
}
- if (!existing_script.is_valid()) {
- menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT);
- }
- if (selection.size() > 1 || existing_script.is_valid()) {
- menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT);
- menu->add_icon_shortcut(get_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_ATTACH_SCRIPT);
- }
+ if (profile_allow_script_editing) {
- menu->add_separator();
- if (selection.size() == 1) {
- menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME);
+ if (!existing_script.is_valid()) {
+ menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT);
+ }
+ if (selection.size() > 1 || existing_script.is_valid()) {
+ menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT);
+ menu->add_icon_shortcut(get_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_ATTACH_SCRIPT);
+ }
}
- menu->add_icon_shortcut(get_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);
- if (scene_tree->get_selected() != edited_scene) {
+ if (profile_allow_editing) {
menu->add_separator();
- menu->add_icon_shortcut(get_icon("MoveUp", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP);
- menu->add_icon_shortcut(get_icon("MoveDown", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN);
- menu->add_icon_shortcut(get_icon("Duplicate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE);
- menu->add_icon_shortcut(get_icon("Reparent", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT);
+ if (selection.size() == 1) {
+ menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME);
+ }
+ menu->add_icon_shortcut(get_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);
+
+ if (scene_tree->get_selected() != edited_scene) {
+ menu->add_separator();
+ menu->add_icon_shortcut(get_icon("MoveUp", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP);
+ menu->add_icon_shortcut(get_icon("MoveDown", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN);
+ menu->add_icon_shortcut(get_icon("Duplicate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE);
+ menu->add_icon_shortcut(get_icon("Reparent", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT);
+ }
}
if (selection.size() == 1) {
- menu->add_icon_shortcut(get_icon("NewRoot", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT);
- menu->add_separator();
- menu->add_icon_shortcut(get_icon("Blend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/merge_from_scene"), TOOL_MERGE_FROM_SCENE);
- menu->add_icon_shortcut(get_icon("CreateNewSceneFrom", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
- menu->add_separator();
+ if (profile_allow_editing) {
+ menu->add_icon_shortcut(get_icon("NewRoot", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT);
+ menu->add_separator();
+ menu->add_icon_shortcut(get_icon("Blend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/merge_from_scene"), TOOL_MERGE_FROM_SCENE);
+ menu->add_icon_shortcut(get_icon("CreateNewSceneFrom", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
+ menu->add_separator();
+ }
menu->add_icon_shortcut(get_icon("CopyNodePath", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH);
+
bool is_external = (selection[0]->get_filename() != "");
if (is_external) {
bool is_inherited = selection[0]->get_scene_inherited_state() != NULL;
bool is_top_level = selection[0]->get_owner() == NULL;
if (is_inherited && is_top_level) {
menu->add_separator();
- menu->add_item(TTR("Clear Inheritance"), TOOL_SCENE_CLEAR_INHERITANCE);
+ if (profile_allow_editing) {
+ menu->add_item(TTR("Clear Inheritance"), TOOL_SCENE_CLEAR_INHERITANCE);
+ }
menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN_INHERITED);
} else if (!is_top_level) {
menu->add_separator();
bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(selection[0]);
bool placeholder = selection[0]->get_scene_instance_load_placeholder();
- menu->add_check_item(TTR("Editable Children"), TOOL_SCENE_EDITABLE_CHILDREN);
- menu->add_check_item(TTR("Load As Placeholder"), TOOL_SCENE_USE_PLACEHOLDER);
- menu->add_item(TTR("Make Local"), TOOL_SCENE_MAKE_LOCAL);
+ if (profile_allow_editing) {
+ menu->add_check_item(TTR("Editable Children"), TOOL_SCENE_EDITABLE_CHILDREN);
+ menu->add_check_item(TTR("Load As Placeholder"), TOOL_SCENE_USE_PLACEHOLDER);
+ menu->add_item(TTR("Make Local"), TOOL_SCENE_MAKE_LOCAL);
+ }
menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN);
- menu->set_item_checked(menu->get_item_idx_from_text(TTR("Editable Children")), editable);
- menu->set_item_checked(menu->get_item_idx_from_text(TTR("Load As Placeholder")), placeholder);
+ if (profile_allow_editing) {
+ menu->set_item_checked(menu->get_item_idx_from_text(TTR("Editable Children")), editable);
+ menu->set_item_checked(menu->get_item_idx_from_text(TTR("Load As Placeholder")), placeholder);
+ }
}
}
}
- if (selection.size() > 1) {
+ if (profile_allow_editing && selection.size() > 1) {
//this is not a commonly used action, it makes no sense for it to be where it was nor always present.
menu->add_separator();
menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME);
@@ -2170,8 +2277,10 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->add_separator();
menu->add_icon_item(get_icon("Help", "EditorIcons"), TTR("Open documentation"), TOOL_OPEN_DOCUMENTATION);
- menu->add_separator();
- menu->add_icon_shortcut(get_icon("Remove", "EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE);
+ if (profile_allow_editing) {
+ menu->add_separator();
+ menu->add_icon_shortcut(get_icon("Remove", "EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE);
+ }
menu->set_size(Size2(1, 1));
menu->set_position(p_menu_pos);
menu->popup();
@@ -2321,6 +2430,30 @@ void SceneTreeDock::_favorite_root_selected(const String &p_class) {
_tool_selected(TOOL_CREATE_FAVORITE, false);
}
+void SceneTreeDock::_feature_profile_changed() {
+
+ Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();
+
+ if (profile.is_valid()) {
+
+ profile_allow_editing = !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCENE_TREE);
+ profile_allow_script_editing = !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT);
+
+ button_add->set_visible(profile_allow_editing);
+ button_instance->set_visible(profile_allow_editing);
+ scene_tree->set_can_rename(profile_allow_editing);
+
+ } else {
+ button_add->set_visible(true);
+ button_instance->set_visible(true);
+ scene_tree->set_can_rename(true);
+ profile_allow_editing = true;
+ profile_allow_script_editing = true;
+ }
+
+ _update_script_button();
+}
+
void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_tool_selected"), &SceneTreeDock::_tool_selected, DEFVAL(false));
@@ -2353,6 +2486,7 @@ void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_script_button"), &SceneTreeDock::_update_script_button);
ClassDB::bind_method(D_METHOD("_favorite_root_selected"), &SceneTreeDock::_favorite_root_selected);
ClassDB::bind_method(D_METHOD("_update_create_root_dialog"), &SceneTreeDock::_update_create_root_dialog);
+ ClassDB::bind_method(D_METHOD("_feature_profile_changed"), &SceneTreeDock::_feature_profile_changed);
ClassDB::bind_method(D_METHOD("instance"), &SceneTreeDock::instance);
@@ -2537,6 +2671,9 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
set_process_input(true);
set_process(true);
+ profile_allow_editing = true;
+ profile_allow_script_editing = true;
+
EDITOR_DEF("interface/editors/show_scene_tree_root_selection", true);
EDITOR_DEF("_use_favorites_root_selection", false);
}
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index 653d0a4eca..e66525d721 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -212,6 +212,11 @@ class SceneTreeDock : public VBoxContainer {
void _update_create_root_dialog();
void _favorite_root_selected(const String &p_class);
+ void _feature_profile_changed();
+
+ bool profile_allow_editing;
+ bool profile_allow_script_editing;
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/translations/extract.py b/editor/translations/extract.py
index fd9b1183c4..2075bd5f3c 100755
--- a/editor/translations/extract.py
+++ b/editor/translations/extract.py
@@ -60,7 +60,7 @@ def process_file(f, fname):
lc = 1
while (l):
- patterns = ['RTR(\"', 'TTR(\"']
+ patterns = ['RTR(\"', 'TTR(\"','TTRC(\"']
idx = 0
pos = 0
while (pos >= 0):
diff --git a/main/performance.cpp b/main/performance.cpp
index 49a08aa8d1..2f7ebf7656 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -154,7 +154,8 @@ float Performance::get_monitor(Monitor p_monitor) const {
case PHYSICS_3D_ISLAND_COUNT: return PhysicsServer::get_singleton()->get_process_info(PhysicsServer::INFO_ISLAND_COUNT);
case AUDIO_OUTPUT_LATENCY: return AudioServer::get_singleton()->get_output_latency();
- default: {}
+ default: {
+ }
}
return 0;
diff --git a/main/tests/test_gdscript.cpp b/main/tests/test_gdscript.cpp
index 7a711e8cc9..8c60b79200 100644
--- a/main/tests/test_gdscript.cpp
+++ b/main/tests/test_gdscript.cpp
@@ -284,7 +284,8 @@ static String _parser_expr(const GDScriptParser::Node *p_expr) {
case GDScriptParser::OperatorNode::OP_BIT_XOR: {
txt = _parser_expr(c_node->arguments[0]) + "^" + _parser_expr(c_node->arguments[1]);
} break;
- default: {}
+ default: {
+ }
}
} break;
diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp
index 0a94690989..059c06c37c 100644
--- a/modules/dds/texture_loader_dds.cpp
+++ b/modules/dds/texture_loader_dds.cpp
@@ -432,7 +432,8 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path,
} break;
- default: {}
+ default: {
+ }
}
wb = PoolVector<uint8_t>::Write();
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp
index 000917507a..193f1bb48d 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/networked_multiplayer_enet.cpp
@@ -690,7 +690,9 @@ size_t NetworkedMultiplayerENet::enet_compress(void *context, const ENetBuffer *
case COMPRESS_ZSTD: {
mode = Compression::MODE_ZSTD;
} break;
- default: { ERR_FAIL_V(0); }
+ default: {
+ ERR_FAIL_V(0);
+ }
}
int req_size = Compression::get_max_compressed_buffer_size(ofs, mode);
@@ -727,7 +729,8 @@ size_t NetworkedMultiplayerENet::enet_decompress(void *context, const enet_uint8
ret = Compression::decompress(outData, outLimit, inData, inLimit, Compression::MODE_ZSTD);
} break;
- default: {}
+ default: {
+ }
}
if (ret < 0) {
return 0;
diff --git a/modules/etc/image_etc.cpp b/modules/etc/image_etc.cpp
index 5410d367db..6f54436bf9 100644
--- a/modules/etc/image_etc.cpp
+++ b/modules/etc/image_etc.cpp
@@ -115,7 +115,8 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f
case Image::FORMAT_RGBA5551: {
detected_channels = Image::DETECTED_RGBA;
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index ee0d5ae055..df8fc2267d 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -1070,7 +1070,8 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G
case GDScriptParser::OperatorNode::OP_BIT_AND: vop = Variant::OP_BIT_AND; break;
case GDScriptParser::OperatorNode::OP_BIT_OR: vop = Variant::OP_BIT_OR; break;
case GDScriptParser::OperatorNode::OP_BIT_XOR: vop = Variant::OP_BIT_XOR; break;
- default: {}
+ default: {
+ }
}
if (vop == Variant::OP_MAX) {
@@ -1125,7 +1126,8 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G
} break;
}
} break;
- default: {}
+ default: {
+ }
}
// It may have found a null, but that's never useful
@@ -3380,7 +3382,8 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
return OK;
}
} break;
- default: {}
+ default: {
+ }
}
return ERR_CANT_RESOLVE;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index e75b8a14a3..ddf880d36c 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -888,7 +888,8 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
case GDScriptTokenizer::TK_OP_SUB: e.op = OperatorNode::OP_NEG; break;
case GDScriptTokenizer::TK_OP_NOT: e.op = OperatorNode::OP_NOT; break;
case GDScriptTokenizer::TK_OP_BIT_INVERT: e.op = OperatorNode::OP_BIT_INVERT; break;
- default: {}
+ default: {
+ }
}
tokenizer->advance();
@@ -1875,7 +1876,9 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to
}
} break;
- default: { break; }
+ default: {
+ break;
+ }
}
//now se if all are constants
if (!all_constants)
@@ -1988,7 +1991,9 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to
return op->arguments[2];
}
} break;
- default: { ERR_FAIL_V(op); }
+ default: {
+ ERR_FAIL_V(op);
+ }
}
ERR_FAIL_V(op);
@@ -6351,7 +6356,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
case Variant::COLOR: {
error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::STRING;
} break;
- default: {}
+ default: {
+ }
}
}
if (error) {
@@ -6469,7 +6475,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
}
}
} break;
- default: {}
+ default: {
+ }
}
p_node->set_datatype(_resolve_type(node_type, p_node->line));
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index abc739d645..cc1f4333fc 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -339,7 +339,8 @@ StringName GDScriptTokenizer::get_token_literal(int p_offset) const {
return "null";
case Variant::BOOL:
return value ? "true" : "false";
- default: {}
+ default: {
+ }
}
}
case TK_OP_AND:
@@ -1302,7 +1303,8 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code)
ERR_FAIL_V(Vector<uint8_t>());
} break;
- default: {}
+ default: {
+ }
};
token_array.push_back(token);
diff --git a/modules/mobile_vr/doc_classes/MobileVRInterface.xml b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
index 0a75ad4784..dbebaae38d 100644
--- a/modules/mobile_vr/doc_classes/MobileVRInterface.xml
+++ b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
@@ -5,7 +5,13 @@
</brief_description>
<description>
This is a generic mobile VR implementation where you need to provide details about the phone and HMD used. It does not rely on any existing framework. This is the most basic interface we have. For the best effect you do need a mobile phone with a gyroscope and accelerometer.
- Note that even though there is no positional tracking the camera will assume the headset is at a height of 1.85 meters.
+ Note that even though there is no positional tracking the camera will assume the headset is at a height of 1.85 meters, you can change this by setting [member eye_height].
+ You can initialise this interface as follows:
+ [codeblock]
+ var interface = ARVRServer.find_interface("Native mobile")
+ if interface and interface.initialize():
+ get_viewport().arvr = true
+ [/codeblock]
</description>
<tutorials>
</tutorials>
@@ -20,6 +26,9 @@
<member name="display_width" type="float" setter="set_display_width" getter="get_display_width">
The width of the display in centimeters.
</member>
+ <member name="eye_height" type="float" setter="set_eye_height" getter="get_eye_height">
+ The height at which the camera is placed in relation to the ground (i.e. [ARVROrigin] node).
+ </member>
<member name="iod" type="float" setter="set_iod" getter="get_iod">
The interocular distance, also known as the interpupillary distance. The distance between the pupils of the left and right eye.
</member>
diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp
index b4fbd417d7..dc7ed03548 100644
--- a/modules/mobile_vr/mobile_vr_interface.cpp
+++ b/modules/mobile_vr/mobile_vr_interface.cpp
@@ -200,6 +200,9 @@ void MobileVRInterface::set_position_from_sensors() {
};
void MobileVRInterface::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_eye_height", "eye_height"), &MobileVRInterface::set_eye_height);
+ ClassDB::bind_method(D_METHOD("get_eye_height"), &MobileVRInterface::get_eye_height);
+
ClassDB::bind_method(D_METHOD("set_iod", "iod"), &MobileVRInterface::set_iod);
ClassDB::bind_method(D_METHOD("get_iod"), &MobileVRInterface::get_iod);
@@ -218,6 +221,7 @@ void MobileVRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_k2", "k"), &MobileVRInterface::set_k2);
ClassDB::bind_method(D_METHOD("get_k2"), &MobileVRInterface::get_k2);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "eye_height", PROPERTY_HINT_RANGE, "0.0,3.0,0.1"), "set_eye_height", "get_eye_height");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "iod", PROPERTY_HINT_RANGE, "4.0,10.0,0.1"), "set_iod", "get_iod");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "display_width", PROPERTY_HINT_RANGE, "5.0,25.0,0.1"), "set_display_width", "get_display_width");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "display_to_lens", PROPERTY_HINT_RANGE, "5.0,25.0,0.1"), "set_display_to_lens", "get_display_to_lens");
@@ -226,6 +230,14 @@ void MobileVRInterface::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "k2", PROPERTY_HINT_RANGE, "0.1,10.0,0.0001"), "set_k2", "get_k2");
}
+void MobileVRInterface::set_eye_height(const real_t p_eye_height) {
+ eye_height = p_eye_height;
+}
+
+real_t MobileVRInterface::get_eye_height() const {
+ return eye_height;
+}
+
void MobileVRInterface::set_iod(const real_t p_iod) {
intraocular_dist = p_iod;
};
@@ -328,6 +340,7 @@ Size2 MobileVRInterface::get_render_targetsize() {
// we use half our window size
Size2 target_size = OS::get_singleton()->get_window_size();
+
target_size.x *= 0.5 * oversample;
target_size.y *= oversample;
diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h
index adc420ea5f..e595daf16e 100644
--- a/modules/mobile_vr/mobile_vr_interface.h
+++ b/modules/mobile_vr/mobile_vr_interface.h
@@ -107,6 +107,9 @@ protected:
static void _bind_methods();
public:
+ void set_eye_height(const real_t p_eye_height);
+ real_t get_eye_height() const;
+
void set_iod(const real_t p_iod);
real_t get_iod() const;
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 84e2303cf6..fe7ced060d 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -100,7 +100,7 @@
#define BINDINGS_GENERATOR_VERSION UINT32_C(8)
-const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n";
+const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN("\t%0 %1_in = %1;\n");
bool BindingsGenerator::verbose_output = false;
@@ -2520,7 +2520,8 @@ void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, Arg
r_iarg.default_argument = Variant::get_type_name(p_val.get_type()) + ".Identity";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
break;
- default: {}
+ default: {
+ }
}
if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type.cname == name_cache.type_Variant && r_iarg.default_argument != "null")
diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp
index d89839f06a..4f38357aa1 100644
--- a/modules/squish/image_compress_squish.cpp
+++ b/modules/squish/image_compress_squish.cpp
@@ -119,7 +119,8 @@ void image_compress_squish(Image *p_image, float p_lossy_quality, Image::Compres
case Image::FORMAT_RGBA5551: {
dc = Image::DETECTED_RGBA;
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index c2ce5f0bf5..d207656705 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -1287,7 +1287,8 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
*r_return = String(color);
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp
index a76e4bc36f..772092fabe 100644
--- a/modules/visual_script/visual_script_expression.cpp
+++ b/modules/visual_script/visual_script_expression.cpp
@@ -1032,7 +1032,8 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() {
case TK_OP_BIT_OR: op = Variant::OP_BIT_OR; break;
case TK_OP_BIT_XOR: op = Variant::OP_BIT_XOR; break;
case TK_OP_BIT_INVERT: op = Variant::OP_BIT_NEGATE; break;
- default: {};
+ default: {
+ };
}
if (op == Variant::OP_MAX) { //stop appending stuff
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index bb0435a679..8fa7d2c0d4 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -1562,7 +1562,8 @@ public:
case VisualScriptPropertySet::ASSIGN_OP_BIT_XOR: {
value = Variant::evaluate(Variant::OP_BIT_XOR, value, p_argument);
} break;
- default: {}
+ default: {
+ }
}
if (index != StringName()) {
diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java
index 48fd076d31..a9edc2f2f4 100644
--- a/platform/android/java/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/src/org/godotengine/godot/Godot.java
@@ -32,6 +32,7 @@ package org.godotengine.godot;
//import android.R;
+import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
@@ -53,7 +54,6 @@ import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
-import android.Manifest;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
@@ -75,7 +75,6 @@ import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
-
import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
import com.google.android.vending.expansion.downloader.DownloaderServiceMarshaller;
@@ -83,10 +82,6 @@ import com.google.android.vending.expansion.downloader.Helpers;
import com.google.android.vending.expansion.downloader.IDownloaderClient;
import com.google.android.vending.expansion.downloader.IDownloaderService;
import com.google.android.vending.expansion.downloader.IStub;
-
-import org.godotengine.godot.input.GodotEditText;
-import org.godotengine.godot.payments.PaymentsManager;
-
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
@@ -96,8 +91,9 @@ import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
-
import javax.microedition.khronos.opengles.GL10;
+import org.godotengine.godot.input.GodotEditText;
+import org.godotengine.godot.payments.PaymentsManager;
public class Godot extends Activity implements SensorEventListener, IDownloaderClient {
diff --git a/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java b/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java
index fb7477c09c..e7e2a3f808 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java
@@ -30,13 +30,12 @@
package org.godotengine.godot;
-import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
-
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;
+import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
/**
* You should start your derived downloader class when this receiver gets the message
diff --git a/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java b/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java
index 91a7b99c36..8e10710c9f 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java
@@ -33,7 +33,6 @@ package org.godotengine.godot;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
-
import com.google.android.vending.expansion.downloader.impl.DownloaderService;
/**
diff --git a/platform/android/java/src/org/godotengine/godot/GodotIO.java b/platform/android/java/src/org/godotengine/godot/GodotIO.java
index 1b2ff61314..98174157ec 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotIO.java
@@ -29,28 +29,27 @@
/*************************************************************************/
package org.godotengine.godot;
-import java.util.HashMap;
-import java.util.Locale;
-import android.net.Uri;
-import android.content.Intent;
-import android.content.res.AssetManager;
-import java.io.InputStream;
-import java.io.IOException;
import android.app.*;
import android.content.*;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.res.AssetManager;
+import android.graphics.*;
+import android.hardware.*;
+import android.media.*;
+import android.net.Uri;
+import android.os.*;
+import android.text.*;
+import android.text.method.*;
+import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.SparseArray;
import android.view.*;
import android.view.inputmethod.InputMethodManager;
-import android.os.*;
-import android.util.Log;
-import android.util.DisplayMetrics;
-import android.graphics.*;
-import android.text.method.*;
-import android.text.*;
-import android.media.*;
-import android.hardware.*;
-import android.content.*;
-import android.content.pm.ActivityInfo;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Locale;
import org.godotengine.godot.input.*;
//android.os.Build
diff --git a/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
index c3d81c5c1d..1432cd3a67 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
@@ -32,14 +32,12 @@ package org.godotengine.godot;
import android.app.Activity;
import android.util.Log;
-
-import org.godotengine.godot.payments.PaymentsManager;
-import org.json.JSONException;
-import org.json.JSONObject;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import org.godotengine.godot.payments.PaymentsManager;
+import org.json.JSONException;
+import org.json.JSONObject;
public class GodotPaymentV3 extends Godot.SingletonBase {
diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java
index ccf78f26f3..d7cd5b4360 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotView.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotView.java
@@ -31,16 +31,15 @@
package org.godotengine.godot;
import android.annotation.SuppressLint;
import android.content.Context;
+import android.content.ContextWrapper;
import android.graphics.PixelFormat;
+import android.hardware.input.InputManager;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import android.content.ContextWrapper;
-import android.view.InputDevice;
-import android.hardware.input.InputManager;
-
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
@@ -51,7 +50,6 @@ import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
-
import org.godotengine.godot.input.InputManagerCompat;
import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener;
/**
diff --git a/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java
index 44bd462ed0..45b739baa0 100644
--- a/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java
+++ b/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java
@@ -30,16 +30,15 @@
package org.godotengine.godot.input;
import android.content.Context;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.widget.EditText;
-import org.godotengine.godot.*;
import android.os.Handler;
import android.os.Message;
-import android.view.inputmethod.InputMethodManager;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
-
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
import java.lang.ref.WeakReference;
+import org.godotengine.godot.*;
public class GodotEditText extends EditText {
// ===========================================================
diff --git a/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java b/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java
index 3b88609cc9..e4bafa7ff9 100644
--- a/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java
+++ b/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java
@@ -23,7 +23,6 @@ import android.os.Build;
import android.os.Handler;
import android.view.InputDevice;
import android.view.MotionEvent;
-
import java.util.HashMap;
import java.util.Map;
diff --git a/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java b/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java
index 1d42aa4464..f872e7af56 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java
@@ -30,13 +30,11 @@
package org.godotengine.godot.payments;
-import com.android.vending.billing.IInAppBillingService;
-
import android.content.Context;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.util.Log;
-
+import com.android.vending.billing.IInAppBillingService;
import java.lang.ref.WeakReference;
abstract public class ConsumeTask {
diff --git a/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java b/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java
index 835779ba00..5424ebb49d 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java
@@ -30,13 +30,6 @@
package org.godotengine.godot.payments;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import org.godotengine.godot.GodotLib;
-import org.godotengine.godot.utils.Crypt;
-import com.android.vending.billing.IInAppBillingService;
-
import android.app.Activity;
import android.app.PendingIntent;
import android.app.ProgressDialog;
@@ -47,6 +40,11 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
+import com.android.vending.billing.IInAppBillingService;
+import org.godotengine.godot.GodotLib;
+import org.godotengine.godot.utils.Crypt;
+import org.json.JSONException;
+import org.json.JSONObject;
abstract public class HandlePurchaseTask {
diff --git a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
index 747a4ffd45..a0dbc432c1 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
@@ -40,17 +40,14 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
-
import com.android.vending.billing.IInAppBillingService;
-
+import java.util.ArrayList;
+import java.util.Arrays;
import org.godotengine.godot.Godot;
import org.godotengine.godot.GodotPaymentV3;
import org.json.JSONException;
import org.json.JSONObject;
-import java.util.ArrayList;
-import java.util.Arrays;
-
public class PaymentsManager {
public static final int BILLING_RESPONSE_RESULT_OK = 0;
diff --git a/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java b/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java
index 000aaa9456..650c5178f0 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java
@@ -30,13 +30,6 @@
package org.godotengine.godot.payments;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import org.godotengine.godot.GodotLib;
-import org.godotengine.godot.utils.Crypt;
-import com.android.vending.billing.IInAppBillingService;
-
import android.app.Activity;
import android.app.PendingIntent;
import android.app.ProgressDialog;
@@ -47,6 +40,11 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
+import com.android.vending.billing.IInAppBillingService;
+import org.godotengine.godot.GodotLib;
+import org.godotengine.godot.utils.Crypt;
+import org.json.JSONException;
+import org.json.JSONObject;
abstract public class PurchaseTask {
diff --git a/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java b/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java
index cf750872d5..daca6ef5ae 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java
@@ -34,14 +34,11 @@ import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
-
import com.android.vending.billing.IInAppBillingService;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import org.json.JSONException;
+import org.json.JSONObject;
abstract public class ReleaseAllConsumablesTask {
diff --git a/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java b/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java
index 6701f9396a..d32c80e8e0 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java
@@ -30,17 +30,6 @@
package org.godotengine.godot.payments;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import org.godotengine.godot.Godot;
-import org.godotengine.godot.GodotLib;
-import org.godotengine.godot.GodotPaymentV3;
-import org.godotengine.godot.utils.Crypt;
-import org.godotengine.godot.utils.HttpRequester;
-import org.godotengine.godot.utils.RequestParams;
-import com.android.vending.billing.IInAppBillingService;
-
import android.app.Activity;
import android.app.PendingIntent;
import android.app.ProgressDialog;
@@ -51,8 +40,16 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
-
+import com.android.vending.billing.IInAppBillingService;
import java.lang.ref.WeakReference;
+import org.godotengine.godot.Godot;
+import org.godotengine.godot.GodotLib;
+import org.godotengine.godot.GodotPaymentV3;
+import org.godotengine.godot.utils.Crypt;
+import org.godotengine.godot.utils.HttpRequester;
+import org.godotengine.godot.utils.RequestParams;
+import org.json.JSONException;
+import org.json.JSONObject;
abstract public class ValidateTask {
diff --git a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
index 3806d4bcad..b61007faa3 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
@@ -37,10 +37,8 @@ import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
-
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
-
import org.apache.http.conn.ssl.SSLSocketFactory;
/**
diff --git a/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
index e9c81eb2e5..e98f533c23 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
@@ -30,6 +30,9 @@
package org.godotengine.godot.utils;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@@ -39,7 +42,6 @@ import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
@@ -64,10 +66,6 @@ import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.util.Log;
-
/**
*
* @author Luis Linietsky <luis.linietsky@gmail.com>
diff --git a/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
index c5778102f6..b9fe0dd0c9 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
@@ -34,7 +34,6 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
-
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 7d2116ba7e..4bbe30a7d1 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -271,6 +271,8 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
- (void)windowDidExitFullScreen:(NSNotification *)notification {
OS_OSX::singleton->zoomed = false;
+ if (!OS_OSX::singleton->resizable)
+ [OS_OSX::singleton->window_object setStyleMask:[OS_OSX::singleton->window_object styleMask] & ~NSWindowStyleMaskResizable];
}
- (void)windowDidChangeBackingProperties:(NSNotification *)notification {
@@ -2300,6 +2302,8 @@ void OS_OSX::set_window_fullscreen(bool p_enabled) {
if (zoomed != p_enabled) {
if (layered_window)
set_window_per_pixel_transparency_enabled(false);
+ if (!resizable)
+ [window_object setStyleMask:[window_object styleMask] | NSWindowStyleMaskResizable];
[window_object toggleFullScreen:nil];
}
zoomed = p_enabled;
@@ -2314,7 +2318,7 @@ void OS_OSX::set_window_resizable(bool p_enabled) {
if (p_enabled)
[window_object setStyleMask:[window_object styleMask] | NSWindowStyleMaskResizable];
- else
+ else if (!zoomed)
[window_object setStyleMask:[window_object styleMask] & ~NSWindowStyleMaskResizable];
resizable = p_enabled;
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 6125455e74..093fb05bae 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -670,7 +670,9 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
mb->set_button_index(BUTTON_XBUTTON2);
mb->set_doubleclick(true);
} break;
- default: { return 0; }
+ default: {
+ return 0;
+ }
}
mb->set_control((wParam & MK_CONTROL) != 0);
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 3562011bc2..885c9ea8bc 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -1405,7 +1405,8 @@ Vector2 TileMap::_map_to_world(int p_x, int p_y, bool p_ignore_ofs) const {
ret += get_cell_transform()[1] * (half_offset == HALF_OFFSET_Y ? 0.5 : -0.5);
}
} break;
- default: {}
+ default: {
+ }
}
}
return ret;
@@ -1480,7 +1481,8 @@ Vector2 TileMap::world_to_map(const Vector2 &p_pos) const {
ret.y += 0.5;
}
} break;
- default: {}
+ default: {
+ }
}
// Account for precision errors on the border (GH-23250).
diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp
index cf1af918f7..ed533ee7a4 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -293,7 +293,8 @@ Light::Light(VisualServer::LightType p_type) {
case VS::LIGHT_DIRECTIONAL: light = VisualServer::get_singleton()->directional_light_create(); break;
case VS::LIGHT_OMNI: light = VisualServer::get_singleton()->omni_light_create(); break;
case VS::LIGHT_SPOT: light = VisualServer::get_singleton()->spot_light_create(); break;
- default: {};
+ default: {
+ };
}
VS::get_singleton()->instance_set_base(get_instance(), light);
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index 83f99a2e3c..395f7b9b35 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -224,7 +224,8 @@ void Spatial::_notification(int p_what) {
#endif
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 0daa574f72..11ce866690 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -857,6 +857,7 @@ AnimationNodeTransition::AnimationNodeTransition() {
time = "time";
current = "current";
prev_current = "prev_current";
+ xfade = 0.0;
enabled_inputs = 0;
for (int i = 0; i < MAX_INPUTS; i++) {
diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp
index feefe3ddd4..84b3f103c5 100644
--- a/scene/animation/animation_cache.cpp
+++ b/scene/animation/animation_cache.cpp
@@ -309,7 +309,8 @@ void AnimationCache::set_all(float p_time, float p_delta) {
}
} break;
- default: {}
+ default: {
+ }
}
}
}
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index fe1b8247ff..2f209ed946 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -1276,7 +1276,8 @@ void AnimationTree::_process_graph(float p_delta) {
t->object->set_indexed(t->subpath, t->value);
} break;
- default: {} //the rest don't matter
+ default: {
+ } //the rest don't matter
}
}
}
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index 3420b48ae3..3cc90c2ad6 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -193,7 +193,8 @@ bool AnimationTreePlayer::_set(const StringName &p_name, const Variant &p_value)
}
} break;
- default: {};
+ default: {
+ };
}
}
@@ -352,7 +353,8 @@ bool AnimationTreePlayer::_get(const StringName &p_name, Variant &r_ret) const {
node["transitions"] = transitions;
} break;
- default: {};
+ default: {
+ };
}
nodes.push_back(node);
@@ -772,7 +774,8 @@ float AnimationTreePlayer::_process_node(const StringName &p_node, AnimationNode
}
} break;
- default: {}
+ default: {
+ }
}
return 0;
@@ -882,7 +885,8 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
tr.track->object->call(method, args[0], args[1], args[2], args[3], args[4]);
}
} break;
- default: {}
+ default: {
+ }
}
}
}
@@ -969,7 +973,8 @@ void AnimationTreePlayer::add_node(NodeType p_type, const StringName &p_node) {
n = memnew(TransitionNode);
} break;
- default: {}
+ default: {
+ }
}
//n->name+=" "+itos(p_node);
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 059e59ea21..5671b41de8 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -86,7 +86,9 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
_dir_entered("..");
} break;
- default: { handled = false; }
+ default: {
+ handled = false;
+ }
}
if (handled)
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 00d6ac3b94..3fbf809012 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -711,7 +711,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
} break;
- default: {}
+ default: {
+ }
}
Item *itp = it;
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 212efa4976..ad41cc4167 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -127,6 +127,9 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
// Activate the clicked tab.
pos.x -= tabs_ofs_cache;
for (int i = first_tab_cache; i <= last_tab_cache; i++) {
+ if (get_tab_hidden(i)) {
+ continue;
+ }
int tab_width = _get_tab_width(i);
if (pos.x < tab_width) {
if (!get_tab_disabled(i)) {
@@ -216,6 +219,9 @@ void TabContainer::_notification(int p_what) {
// Check if all tabs would fit into the header area.
int all_tabs_width = 0;
for (int i = 0; i < tabs.size(); i++) {
+ if (get_tab_hidden(i)) {
+ continue;
+ }
int tab_width = _get_tab_width(i);
all_tabs_width += tab_width;
@@ -241,6 +247,9 @@ void TabContainer::_notification(int p_what) {
all_tabs_width = 0;
Vector<int> tab_widths;
for (int i = first_tab_cache; i < tabs.size(); i++) {
+ if (get_tab_hidden(i)) {
+ continue;
+ }
int tab_width = _get_tab_width(i);
if (all_tabs_width + tab_width > header_width && tab_widths.size() > 0)
break;
@@ -267,6 +276,9 @@ void TabContainer::_notification(int p_what) {
// Draw all visible tabs.
int x = 0;
for (int i = 0; i < tab_widths.size(); i++) {
+ if (get_tab_hidden(i)) {
+ continue;
+ }
Ref<StyleBox> tab_style;
Color font_color;
if (get_tab_disabled(i + first_tab_cache)) {
@@ -354,7 +366,7 @@ int TabContainer::_get_tab_width(int p_index) const {
ERR_FAIL_INDEX_V(p_index, get_tab_count(), 0);
Control *control = Object::cast_to<Control>(_get_tabs()[p_index]);
- if (!control || control->is_set_as_toplevel())
+ if (!control || control->is_set_as_toplevel() || get_tab_hidden(p_index))
return 0;
// Get the width of the text displayed on the tab.
@@ -765,6 +777,36 @@ bool TabContainer::get_tab_disabled(int p_tab) const {
return false;
}
+void TabContainer::set_tab_hidden(int p_tab, bool p_hidden) {
+
+ Control *child = _get_tab(p_tab);
+ ERR_FAIL_COND(!child);
+ child->set_meta("_tab_hidden", p_hidden);
+ update();
+ for (int i = 0; i < get_tab_count(); i++) {
+ int try_tab = (p_tab + 1 + i) % get_tab_count();
+ if (get_tab_disabled(try_tab) || get_tab_hidden(try_tab)) {
+ continue;
+ }
+
+ set_current_tab(try_tab);
+ return;
+ }
+
+ //assumed no other tab can be switched to, just hide
+ child->hide();
+}
+
+bool TabContainer::get_tab_hidden(int p_tab) const {
+
+ Control *child = _get_tab(p_tab);
+ ERR_FAIL_COND_V(!child, false);
+ if (child->has_meta("_tab_hidden"))
+ return child->get_meta("_tab_hidden");
+ else
+ return false;
+}
+
void TabContainer::get_translatable_strings(List<String> *p_strings) const {
Vector<Control *> tabs = _get_tabs();
diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h
index c110f041d0..f7a9fb64fd 100644
--- a/scene/gui/tab_container.h
+++ b/scene/gui/tab_container.h
@@ -96,6 +96,9 @@ public:
void set_tab_disabled(int p_tab, bool p_disabled);
bool get_tab_disabled(int p_tab) const;
+ void set_tab_hidden(int p_tab, bool p_hidden);
+ bool get_tab_hidden(int p_tab) const;
+
int get_tab_count() const;
void set_current_tab(int p_current);
int get_current_tab() const;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 679b752fa3..7f00e7bd24 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -962,7 +962,8 @@ int Tree::compute_item_height(TreeItem *p_item) const {
}
} break;
- default: {}
+ default: {
+ }
}
}
int item_min_height = p_item->get_custom_minimum_height();
@@ -2020,7 +2021,9 @@ void Tree::text_editor_enter(String p_text) {
//popup_edited_item->edited_signal.call( popup_edited_item_col );
} break;
- default: { ERR_FAIL(); }
+ default: {
+ ERR_FAIL();
+ }
}
item_edited(popup_edited_item_col, popup_edited_item);
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index b6efca9acc..2e54424c90 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -1459,7 +1459,8 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant,
_find_resources(v);
}
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/scene/resources/sky.cpp b/scene/resources/sky.cpp
index f9f8ff19e4..48945d4e63 100644
--- a/scene/resources/sky.cpp
+++ b/scene/resources/sky.cpp
@@ -553,10 +553,10 @@ ProceduralSky::ProceduralSky(bool p_desaturate) {
ground_energy = 1;
if (p_desaturate) {
- sky_top_color.set_hsv(sky_top_color.get_h(),0,sky_top_color.get_v());
- sky_horizon_color.set_hsv(sky_horizon_color.get_h(),0,sky_horizon_color.get_v());
- ground_bottom_color.set_hsv(ground_bottom_color.get_h(),0,ground_bottom_color.get_v());
- ground_horizon_color.set_hsv(ground_horizon_color.get_h(),0,ground_horizon_color.get_v());
+ sky_top_color.set_hsv(sky_top_color.get_h(), 0, sky_top_color.get_v());
+ sky_horizon_color.set_hsv(sky_horizon_color.get_h(), 0, sky_horizon_color.get_v());
+ ground_bottom_color.set_hsv(ground_bottom_color.get_h(), 0, ground_bottom_color.get_v());
+ ground_horizon_color.set_hsv(ground_horizon_color.get_h(), 0, ground_horizon_color.get_v());
}
sun_color = Color(1, 1, 1);
sun_latitude = 35;
diff --git a/scene/resources/sky.h b/scene/resources/sky.h
index 7327b2a627..3a6f44e11b 100644
--- a/scene/resources/sky.h
+++ b/scene/resources/sky.h
@@ -191,7 +191,7 @@ public:
virtual RID get_rid() const;
- ProceduralSky(bool p_desaturate=false);
+ ProceduralSky(bool p_desaturate = false);
~ProceduralSky();
};
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index 83f29503fa..c0abee2030 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -397,7 +397,8 @@ Array SurfaceTool::commit_to_arrays() {
a[i] = array;
} break;
- default: {}
+ default: {
+ }
}
}
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index bac10a1cd5..fdb6f2ce09 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -839,7 +839,8 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
case VisualShaderNode::PORT_TYPE_VECTOR: code += String() + "\tvec3 " + outputs[i] + ";\n"; break;
case VisualShaderNode::PORT_TYPE_BOOLEAN: code += String() + "\tbool " + outputs[i] + ";\n"; break;
case VisualShaderNode::PORT_TYPE_TRANSFORM: code += String() + "\tmat4 " + outputs[i] + ";\n"; break;
- default: {}
+ default: {
+ }
}
}
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index f0fbbafe1c..b4c3670a7b 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -196,7 +196,8 @@ void BodySW::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) {
angular_damp = p_value;
} break;
- default: {}
+ default: {
+ }
}
}
@@ -226,7 +227,8 @@ real_t BodySW::get_param(PhysicsServer::BodyParameter p_param) const {
return angular_damp;
} break;
- default: {}
+ default: {
+ }
}
return 0;
@@ -474,7 +476,8 @@ void BodySW::integrate_forces(real_t p_step) {
_compute_area_gravity_and_dampenings(aa[i].area);
stopped = mode == PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE;
} break;
- default: {}
+ default: {
+ }
}
}
}
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index 60bcb2e28e..60bbcef4b6 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -174,7 +174,8 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, real_t p_value)
angular_damp = p_value;
} break;
- default: {}
+ default: {
+ }
}
}
@@ -206,7 +207,8 @@ real_t Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const {
return angular_damp;
} break;
- default: {}
+ default: {
+ }
}
return 0;
@@ -443,7 +445,8 @@ void Body2DSW::integrate_forces(real_t p_step) {
_compute_area_gravity_and_dampenings(aa[i].area);
stopped = mode == Physics2DServer::AREA_SPACE_OVERRIDE_REPLACE;
} break;
- default: {}
+ default: {
+ }
}
}
}
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 1f9d263354..33714a79b2 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -3620,7 +3620,8 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
case TYPE_FLOAT: {
nv.real = -cn->values[i].real;
} break;
- default: {}
+ default: {
+ }
}
values.push_back(nv);
@@ -4822,7 +4823,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
case TYPE_MAT2: limit = 2; break;
case TYPE_MAT3: limit = 3; break;
case TYPE_MAT4: limit = 4; break;
- default: {}
+ default: {
+ }
}
for (int i = 0; i < limit; i++) {
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index 4adf53c183..15f37dd6d1 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -55,16 +55,18 @@ void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2
int child_item_count = p_canvas_item->child_items.size();
VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw();
for (int i = 0; i < child_item_count; i++) {
- if (r_items) {
- r_items[r_index] = child_items[i];
- child_items[i]->ysort_xform = p_transform;
- child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]);
- }
+ if (child_items[i]->visible) {
+ if (r_items) {
+ r_items[r_index] = child_items[i];
+ child_items[i]->ysort_xform = p_transform;
+ child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]);
+ }
- r_index++;
+ r_index++;
- if (child_items[i]->sort_y)
- _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_index);
+ if (child_items[i]->sort_y)
+ _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_index);
+ }
}
}
@@ -393,6 +395,10 @@ void VisualServerCanvas::canvas_item_set_visible(RID p_item, bool p_visible) {
ERR_FAIL_COND(!canvas_item);
canvas_item->visible = p_visible;
+
+ if (canvas_item->parent.is_valid() && canvas_item_owner.owns(canvas_item->parent)) {
+ _mark_ysort_dirty(canvas_item_owner.get(canvas_item->parent), canvas_item_owner);
+ }
}
void VisualServerCanvas::canvas_item_set_light_mask(RID p_item, int p_mask) {
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index 2590e29aef..a5858ab661 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -399,7 +399,8 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
VSG::scene_render->free(gi_probe->probe_instance);
} break;
- default: {}
+ default: {
+ }
}
if (instance->base_data) {
@@ -476,7 +477,8 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
gi_probe->probe_instance = VSG::scene_render->gi_probe_instance_create();
} break;
- default: {}
+ default: {
+ }
}
VSG::storage->instance_add_dependency(p_base, instance);
@@ -524,7 +526,8 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
gi_probe_update_list.remove(&gi_probe->update_element);
}
} break;
- default: {}
+ default: {
+ }
}
instance->scenario = NULL;
@@ -556,7 +559,8 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
gi_probe_update_list.add(&gi_probe->update_element);
}
} break;
- default: {}
+ default: {
+ }
}
_instance_queue_update(instance, true, true);
@@ -671,7 +675,8 @@ void VisualServerScene::instance_set_visible(RID p_instance, bool p_visible) {
}
} break;
- default: {}
+ default: {
+ }
}
}
inline bool is_geometry_instance(VisualServer::InstanceType p_type) {
@@ -848,7 +853,8 @@ void VisualServerScene::instance_geometry_set_flag(RID p_instance, VS::InstanceF
instance->redraw_if_visible = p_enabled;
} break;
- default: {}
+ default: {
+ }
}
}
void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting) {
@@ -1040,7 +1046,8 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
new_aabb = VSG::storage->lightmap_capture_get_bounds(p_instance->base);
} break;
- default: {}
+ default: {
+ }
}
// <Zylann> This is why I didn't re-use Instance::aabb to implement custom AABBs
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index 9ad3e4a308..e7f60c2c1f 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -295,8 +295,8 @@ void VisualServerViewport::draw_viewports() {
if (vp->use_arvr && arvr_interface.is_valid()) {
// override our size, make sure it matches our required size
- Size2 size = arvr_interface->get_render_targetsize();
- VSG::storage->render_target_set_size(vp->render_target, size.x, size.y);
+ vp->size = arvr_interface->get_render_targetsize();
+ VSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y);
// render mono or left eye first
ARVRInterface::Eyes leftOrMono = arvr_interface->is_stereo() ? ARVRInterface::EYE_LEFT : ARVRInterface::EYE_MONO;