summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/image.cpp151
-rw-r--r--core/image.h1
-rw-r--r--core/math/math_funcs.h6
-rw-r--r--core/object.cpp12
-rw-r--r--doc/classes/Image.xml2
-rw-r--r--doc/classes/String.xml1
-rw-r--r--editor/editor_node.cpp4
-rw-r--r--editor/editor_settings.cpp2
-rw-r--r--editor/editor_themes.cpp2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp27
-rw-r--r--editor/plugins/animation_player_editor_plugin.h1
-rw-r--r--editor/script_editor_debugger.cpp20
-rw-r--r--editor/script_editor_debugger.h1
-rw-r--r--modules/bullet/rigid_body_bullet.cpp10
-rw-r--r--platform/osx/export/export.cpp22
-rw-r--r--scene/gui/line_edit.cpp2
-rw-r--r--scene/gui/text_edit.cpp5
17 files changed, 229 insertions, 40 deletions
diff --git a/core/image.cpp b/core/image.cpp
index 99d5eab864..30af724de9 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -725,6 +725,131 @@ static void _scale_nearest(const uint8_t *__restrict p_src, uint8_t *__restrict
}
}
+#define LANCZOS_TYPE 3
+
+static float _lanczos(float p_x) {
+ return Math::abs(p_x) >= LANCZOS_TYPE ? 0 : Math::sincn(p_x) * Math::sincn(p_x / LANCZOS_TYPE);
+}
+
+template <int CC, class T>
+static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
+
+ int32_t src_width = p_src_width;
+ int32_t src_height = p_src_height;
+ int32_t dst_height = p_dst_height;
+ int32_t dst_width = p_dst_width;
+
+ uint32_t buffer_size = src_height * dst_width * CC;
+ float *buffer = memnew_arr(float, buffer_size); // Store the first pass in a buffer
+
+ { // FIRST PASS (horizontal)
+
+ float x_scale = float(src_width) / float(dst_width);
+
+ float scale_factor = MAX(x_scale, 1); // A larger kernel is required only when downscaling
+ int32_t half_kernel = LANCZOS_TYPE * scale_factor;
+
+ float *kernel = memnew_arr(float, half_kernel * 2 - 1);
+
+ for (int32_t buffer_x = 0; buffer_x < dst_width; buffer_x++) {
+
+ float src_real_x = buffer_x * x_scale;
+ int32_t src_x = src_real_x;
+
+ int32_t start_x = MAX(0, src_x - half_kernel + 1);
+ int32_t end_x = MIN(src_width - 1, src_x + half_kernel);
+
+ // Create the kernel used by all the pixels of the column
+ for (int32_t target_x = start_x; target_x <= end_x; target_x++)
+ kernel[target_x - start_x] = _lanczos((src_real_x - target_x) / scale_factor);
+
+ for (int32_t buffer_y = 0; buffer_y < src_height; buffer_y++) {
+
+ float pixel[CC] = { 0 };
+ float weight = 0;
+
+ for (int32_t target_x = start_x; target_x <= end_x; target_x++) {
+
+ float lanczos_val = kernel[target_x - start_x];
+ weight += lanczos_val;
+
+ const T *__restrict src_data = ((const T *)p_src) + (buffer_y * src_width + target_x) * CC;
+
+ for (uint32_t i = 0; i < CC; i++) {
+ if (sizeof(T) == 2) //half float
+ pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val;
+ else
+ pixel[i] += src_data[i] * lanczos_val;
+ }
+ }
+
+ float *dst_data = ((float *)buffer) + (buffer_y * dst_width + buffer_x) * CC;
+
+ for (uint32_t i = 0; i < CC; i++)
+ dst_data[i] = pixel[i] / weight; // Normalize the sum of all the samples
+ }
+ }
+
+ memdelete_arr(kernel);
+ } // End of first pass
+
+ { // SECOND PASS (vertical + result)
+
+ float y_scale = float(src_height) / float(dst_height);
+
+ float scale_factor = MAX(y_scale, 1);
+ int32_t half_kernel = LANCZOS_TYPE * scale_factor;
+
+ float *kernel = memnew_arr(float, half_kernel * 2 - 1);
+
+ for (int32_t dst_y = 0; dst_y < dst_height; dst_y++) {
+
+ float buffer_real_y = dst_y * y_scale;
+ int32_t buffer_y = buffer_real_y;
+
+ int32_t start_y = MAX(0, buffer_y - half_kernel + 1);
+ int32_t end_y = MIN(src_height - 1, buffer_y + half_kernel);
+
+ for (int32_t target_y = start_y; target_y <= end_y; target_y++)
+ kernel[target_y - start_y] = _lanczos((buffer_real_y - target_y) / scale_factor);
+
+ for (int32_t dst_x = 0; dst_x < dst_width; dst_x++) {
+
+ float pixel[CC] = { 0 };
+ float weight = 0;
+
+ for (int32_t target_y = start_y; target_y <= end_y; target_y++) {
+
+ float lanczos_val = kernel[target_y - start_y];
+ weight += lanczos_val;
+
+ float *buffer_data = ((float *)buffer) + (target_y * dst_width + dst_x) * CC;
+
+ for (uint32_t i = 0; i < CC; i++)
+ pixel[i] += buffer_data[i] * lanczos_val;
+ }
+
+ T *dst_data = ((T *)p_dst) + (dst_y * dst_width + dst_x) * CC;
+
+ for (uint32_t i = 0; i < CC; i++) {
+ pixel[i] /= weight;
+
+ if (sizeof(T) == 1) //byte
+ dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255);
+ else if (sizeof(T) == 2) //half float
+ dst_data[i] = Math::make_half_float(pixel[i]);
+ else // float
+ dst_data[i] = pixel[i];
+ }
+ }
+ }
+
+ memdelete_arr(kernel);
+ } // End of second pass
+
+ memdelete_arr(buffer);
+}
+
static void _overlay(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, float p_alpha, uint32_t p_width, uint32_t p_height, uint32_t p_pixel_size) {
uint16_t alpha = CLAMP((uint16_t)(p_alpha * 256.0f), 0, 256);
@@ -939,6 +1064,31 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
}
}
} break;
+ case INTERPOLATE_LANCZOS: {
+
+ if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
+ switch (get_format_pixel_size(format)) {
+ case 1: _scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 2: _scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 3: _scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 4: _scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ }
+ } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
+ switch (get_format_pixel_size(format)) {
+ case 4: _scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 8: _scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 12: _scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 16: _scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ }
+ } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
+ switch (get_format_pixel_size(format)) {
+ case 2: _scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 4: _scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 6: _scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 8: _scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ }
+ }
+ } break;
}
r = PoolVector<uint8_t>::Read();
@@ -2685,6 +2835,7 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(INTERPOLATE_BILINEAR);
BIND_ENUM_CONSTANT(INTERPOLATE_CUBIC);
BIND_ENUM_CONSTANT(INTERPOLATE_TRILINEAR);
+ BIND_ENUM_CONSTANT(INTERPOLATE_LANCZOS);
BIND_ENUM_CONSTANT(ALPHA_NONE);
BIND_ENUM_CONSTANT(ALPHA_BIT);
diff --git a/core/image.h b/core/image.h
index 69a42f169a..752ef20208 100644
--- a/core/image.h
+++ b/core/image.h
@@ -109,6 +109,7 @@ public:
INTERPOLATE_BILINEAR,
INTERPOLATE_CUBIC,
INTERPOLATE_TRILINEAR,
+ INTERPOLATE_LANCZOS,
/* INTERPOLATE_TRICUBIC, */
/* INTERPOLATE GAUSS */
};
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index a75f2fb4ab..82b5b56c01 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -61,6 +61,12 @@ public:
static _ALWAYS_INLINE_ double sinh(double p_x) { return ::sinh(p_x); }
static _ALWAYS_INLINE_ float sinh(float p_x) { return ::sinhf(p_x); }
+ static _ALWAYS_INLINE_ float sinc(float p_x) { return p_x == 0 ? 1 : ::sin(p_x) / p_x; }
+ static _ALWAYS_INLINE_ double sinc(double p_x) { return p_x == 0 ? 1 : ::sin(p_x) / p_x; }
+
+ static _ALWAYS_INLINE_ float sincn(float p_x) { return sinc(Math_PI * p_x); }
+ static _ALWAYS_INLINE_ double sincn(double p_x) { return sinc(Math_PI * p_x); }
+
static _ALWAYS_INLINE_ double cosh(double p_x) { return ::cosh(p_x); }
static _ALWAYS_INLINE_ float cosh(float p_x) { return ::coshf(p_x); }
diff --git a/core/object.cpp b/core/object.cpp
index 937aa3c745..2a4ab93a6d 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -608,18 +608,16 @@ Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) co
}
bool valid = false;
- Variant current_value = get(p_names[0]);
+ Variant current_value = get(p_names[0], &valid);
for (int i = 1; i < p_names.size(); i++) {
current_value = current_value.get_named(p_names[i], &valid);
- if (!valid) {
- if (r_valid)
- *r_valid = false;
- return Variant();
- }
+ if (!valid)
+ break;
}
if (r_valid)
- *r_valid = true;
+ *r_valid = valid;
+
return current_value;
}
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 641bd64599..8dfabdd884 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -603,6 +603,8 @@
If the image does not have mipmaps, they will be generated and used internally, but no mipmaps will be generated on the resulting image. (Note that if you intend to scale multiple copies of the original image, it's better to call [code]generate_mipmaps[/code] on it in advance, to avoid wasting processing power in generating them again and again.)
On the other hand, if the image already has mipmaps, they will be used, and a new set will be generated for the resulting image.
</constant>
+ <constant name="INTERPOLATE_LANCZOS" value="4" enum="Interpolation">
+ </constant>
<constant name="ALPHA_NONE" value="0" enum="AlphaMode">
</constant>
<constant name="ALPHA_BIT" value="1" enum="AlphaMode">
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index 526a9427dc..e06f0738b8 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -7,6 +7,7 @@
This is the built-in string class (and the one used by GDScript). It supports Unicode and provides all necessary means for string handling. Strings are reference counted and use a copy-on-write approach, so passing them around is cheap in resources.
</description>
<tutorials>
+ <link>https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/gdscript_format_string.html</link>
</tutorials>
<methods>
<method name="String">
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index fed1f6b4fa..40e05940a7 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -1015,8 +1015,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
y = (img->get_height() - size) / 2;
img->crop_from_point(x, y, size, size);
- // We could get better pictures with better filters
- img->resize(preview_size, preview_size, Image::INTERPOLATE_CUBIC);
+ img->resize(preview_size, preview_size, Image::INTERPOLATE_LANCZOS);
}
img->convert(Image::FORMAT_RGB8);
@@ -5997,7 +5996,6 @@ EditorNode::EditorNode() {
node_dock = memnew(NodeDock);
filesystem_dock = memnew(FileSystemDock(this));
- filesystem_dock->connect("open", this, "open_request");
filesystem_dock->connect("inherit", this, "_inherit_request");
filesystem_dock->connect("instance", this, "_instance_request");
filesystem_dock->connect("display_mode_changed", this, "_save_docks");
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index c32dcb0ace..8f26663f81 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -651,7 +651,7 @@ void EditorSettings::_load_default_text_editor_theme() {
_initial_set("text_editor/highlighting/executing_line_color", Color(0.2, 0.8, 0.2, 0.4));
_initial_set("text_editor/highlighting/code_folding_color", Color(0.8, 0.8, 0.8, 0.8));
_initial_set("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1));
- _initial_set("text_editor/highlighting/search_result_border_color", Color(0.1, 0.45, 0.1, 1));
+ _initial_set("text_editor/highlighting/search_result_border_color", Color(0.41, 0.61, 0.91, 0.38));
}
bool EditorSettings::_save_text_editor_theme(String p_file) {
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index f74e913208..e1addaa532 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1121,7 +1121,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color executing_line_color = Color(0.2, 0.8, 0.2, 0.4);
const Color code_folding_color = alpha3;
const Color search_result_color = alpha1;
- const Color search_result_border_color = alpha3;
+ const Color search_result_border_color = Color(0.41, 0.61, 0.91, 0.38);
EditorSettings *setting = EditorSettings::get_singleton();
String text_editor_color_theme = setting->get("text_editor/theme/color_theme");
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 7c075b5635..0a9436952b 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -129,8 +129,10 @@ void AnimationPlayerEditor::_notification(int p_what) {
autoplay_icon = get_icon("AutoPlay", "EditorIcons");
stop->set_icon(get_icon("Stop", "EditorIcons"));
+ onion_toggle->set_icon(get_icon("Onion", "EditorIcons"));
+ onion_skinning->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));
+
pin->set_icon(get_icon("Pin", "EditorIcons"));
- onion_skinning->set_icon(get_icon("Onion", "EditorIcons"));
tool_anim->add_style_override("normal", get_stylebox("normal", "Button"));
track_editor->get_edit_menu()->add_style_override("normal", get_stylebox("normal", "Button"));
@@ -1229,7 +1231,6 @@ void AnimationPlayerEditor::_onion_skinning_menu(int p_option) {
case ONION_SKINNING_ENABLE: {
onion.enabled = !onion.enabled;
- menu->set_item_checked(idx, onion.enabled);
if (onion.enabled)
_start_onion_skinning();
@@ -1708,19 +1709,21 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
hb->add_child(track_editor->get_edit_menu());
+ hb->add_child(memnew(VSeparator));
+
+ onion_toggle = memnew(ToolButton);
+ onion_toggle->set_toggle_mode(true);
+ onion_toggle->set_tooltip(TTR("Enable Onion Skinning"));
+ onion_toggle->connect("pressed", this, "_onion_skinning_menu", varray(ONION_SKINNING_ENABLE));
+ hb->add_child(onion_toggle);
+
onion_skinning = memnew(MenuButton);
- //onion_skinning->set_flat(false);
- onion_skinning->set_tooltip(TTR("Onion Skinning"));
- onion_skinning->get_popup()->add_check_shortcut(ED_SHORTCUT("animation_player_editor/onion_skinning", TTR("Enable Onion Skinning")), ONION_SKINNING_ENABLE);
- onion_skinning->get_popup()->add_separator();
- onion_skinning->get_popup()->add_item(TTR("Directions"), -1);
- onion_skinning->get_popup()->set_item_disabled(onion_skinning->get_popup()->get_item_count() - 1, true);
+ onion_skinning->set_tooltip(TTR("Onion Skinning Options"));
+ onion_skinning->get_popup()->add_separator(TTR("Directions"));
onion_skinning->get_popup()->add_check_item(TTR("Past"), ONION_SKINNING_PAST);
onion_skinning->get_popup()->set_item_checked(onion_skinning->get_popup()->get_item_count() - 1, true);
onion_skinning->get_popup()->add_check_item(TTR("Future"), ONION_SKINNING_FUTURE);
- onion_skinning->get_popup()->add_separator();
- onion_skinning->get_popup()->add_item(TTR("Depth"), -1);
- onion_skinning->get_popup()->set_item_disabled(onion_skinning->get_popup()->get_item_count() - 1, true);
+ onion_skinning->get_popup()->add_separator(TTR("Depth"));
onion_skinning->get_popup()->add_radio_check_item(TTR("1 step"), ONION_SKINNING_1_STEP);
onion_skinning->get_popup()->set_item_checked(onion_skinning->get_popup()->get_item_count() - 1, true);
onion_skinning->get_popup()->add_radio_check_item(TTR("2 steps"), ONION_SKINNING_2_STEPS);
@@ -1731,6 +1734,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
onion_skinning->get_popup()->add_check_item(TTR("Include Gizmos (3D)"), ONION_SKINNING_INCLUDE_GIZMOS);
hb->add_child(onion_skinning);
+ hb->add_child(memnew(VSeparator));
+
pin = memnew(ToolButton);
pin->set_toggle_mode(true);
pin->set_tooltip(TTR("Pin AnimationPlayer"));
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 9085c70410..c6ab6c5e30 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -102,6 +102,7 @@ class AnimationPlayerEditor : public VBoxContainer {
Button *autoplay;
MenuButton *tool_anim;
+ ToolButton *onion_toggle;
MenuButton *onion_skinning;
ToolButton *pin;
SpinBox *frame;
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index 1da8bf874c..a661c2cfc3 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -299,6 +299,7 @@ void ScriptEditorDebugger::_scene_tree_rmb_selected(const Vector2 &p_position) {
item_menu->clear();
item_menu->add_icon_item(get_icon("CreateNewSceneFrom", "EditorIcons"), TTR("Save Branch as Scene"), ITEM_MENU_SAVE_REMOTE_NODE);
+ item_menu->add_icon_item(get_icon("CopyNodePath", "EditorIcons"), TTR("Copy Node Path"), ITEM_MENU_COPY_NODE_PATH);
item_menu->set_global_position(get_global_mouse_position());
item_menu->popup();
}
@@ -396,6 +397,7 @@ Size2 ScriptEditorDebugger::get_minimum_size() const {
ms.y = MAX(ms.y, 250 * EDSCALE);
return ms;
}
+
void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_data) {
if (p_msg == "debug_enter") {
@@ -1930,6 +1932,24 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) {
file_dialog->popup_centered_ratio();
} break;
+ case ITEM_MENU_COPY_NODE_PATH: {
+
+ TreeItem *ti = inspect_scene_tree->get_selected();
+ String text = ti->get_text(0);
+
+ if (ti->get_parent() == NULL) {
+ text = ".";
+ } else if (ti->get_parent()->get_parent() == NULL) {
+ text = ".";
+ } else {
+ while (ti->get_parent()->get_parent() != inspect_scene_tree->get_root()) {
+ ti = ti->get_parent();
+ text = ti->get_text(0) + "/" + text;
+ }
+ }
+
+ OS::get_singleton()->set_clipboard(text);
+ } break;
}
}
diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h
index f7afe6bf72..05dcab0f80 100644
--- a/editor/script_editor_debugger.h
+++ b/editor/script_editor_debugger.h
@@ -66,6 +66,7 @@ class ScriptEditorDebugger : public Control {
enum ItemMenu {
ITEM_MENU_COPY_ERROR,
ITEM_MENU_SAVE_REMOTE_NODE,
+ ITEM_MENU_COPY_NODE_PATH,
};
AcceptDialog *msgdialog;
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index e5f70a0b34..733a900396 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -741,22 +741,20 @@ void RigidBodyBullet::set_continuous_collision_detection(bool p_enable) {
if (p_enable) {
// This threshold enable CCD if the object moves more than
// 1 meter in one simulation frame
- btBody->setCcdMotionThreshold(0.1);
+ btBody->setCcdMotionThreshold(1e-7);
/// Calculate using the rule writte below the CCD swept sphere radius
/// CCD works on an embedded sphere of radius, make sure this radius
/// is embedded inside the convex objects, preferably smaller:
/// for an object of dimensions 1 meter, try 0.2
- btScalar radius;
+ btScalar radius(1.0);
if (btBody->getCollisionShape()) {
btVector3 center;
btBody->getCollisionShape()->getBoundingSphere(center, radius);
- } else {
- radius = 0;
}
btBody->setCcdSweptSphereRadius(radius * 0.2);
} else {
- btBody->setCcdMotionThreshold(0.);
+ btBody->setCcdMotionThreshold(10000.0);
btBody->setCcdSweptSphereRadius(0.);
}
}
@@ -834,7 +832,7 @@ void RigidBodyBullet::reload_shapes() {
btBody->updateInertiaTensor();
reload_kinematic_shapes();
-
+ set_continuous_collision_detection(btBody->getCcdMotionThreshold() < 9998.0);
reload_body();
}
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 89212b0e5e..d0e39d1638 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -121,7 +121,7 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
@@ -542,11 +542,21 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
iconpath = ProjectSettings::get_singleton()->get("application/config/icon");
if (iconpath != "") {
- Ref<Image> icon;
- icon.instance();
- icon->load(iconpath);
- if (!icon->empty()) {
- _make_icon(icon, data);
+ if (iconpath.get_extension() == "icns") {
+ FileAccess *icon = FileAccess::open(iconpath, FileAccess::READ);
+ if (icon) {
+ data.resize(icon->get_len());
+ icon->get_buffer(&data.write[0], icon->get_len());
+ icon->close();
+ memdelete(icon);
+ }
+ } else {
+ Ref<Image> icon;
+ icon.instance();
+ icon->load(iconpath);
+ if (!icon->empty()) {
+ _make_icon(icon, data);
+ }
}
}
//bleh?
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index b10ddfaf70..2d18a80833 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -613,7 +613,7 @@ void LineEdit::_notification(int p_what) {
#endif
case NOTIFICATION_RESIZED: {
- window_pos = 0; //force scroll back since it's expanding to text length
+ window_pos = 0;
set_cursor_position(get_cursor_position());
} break;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 10bd9e2a8b..86b99b3c6d 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1072,10 +1072,7 @@ void TextEdit::_notification(int p_what) {
}
if ((char_ofs + char_margin + char_w) >= xmargin_end) {
- if (syntax_coloring)
- continue;
- else
- break;
+ break;
}
bool in_search_result = false;