Merge pull request #49237 from akien-mga/3.x-cherrypicks

This commit is contained in:
Rémi Verschelde 2021-06-01 13:35:56 +02:00 committed by GitHub
commit e0fb05ad30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 359 additions and 106 deletions

View file

@ -760,7 +760,7 @@ int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
unsigned int hour = ((datetime.has(HOUR_KEY)) ? static_cast<unsigned int>(datetime[HOUR_KEY]) : 0);
unsigned int day = ((datetime.has(DAY_KEY)) ? static_cast<unsigned int>(datetime[DAY_KEY]) : 1);
unsigned int month = ((datetime.has(MONTH_KEY)) ? static_cast<unsigned int>(datetime[MONTH_KEY]) : 1);
unsigned int year = ((datetime.has(YEAR_KEY)) ? static_cast<unsigned int>(datetime[YEAR_KEY]) : 0);
unsigned int year = ((datetime.has(YEAR_KEY)) ? static_cast<unsigned int>(datetime[YEAR_KEY]) : 1970);
/// How many days come before each month (0-12)
static const unsigned short int DAYS_PAST_THIS_YEAR_TABLE[2][13] = {
@ -771,15 +771,14 @@ int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
};
ERR_FAIL_COND_V_MSG(second > 59, 0, "Invalid second value of: " + itos(second) + ".");
ERR_FAIL_COND_V_MSG(minute > 59, 0, "Invalid minute value of: " + itos(minute) + ".");
ERR_FAIL_COND_V_MSG(hour > 23, 0, "Invalid hour value of: " + itos(hour) + ".");
ERR_FAIL_COND_V_MSG(year == 0, 0, "Years before 1 AD are not supported. Value passed: " + itos(year) + ".");
ERR_FAIL_COND_V_MSG(month > 12 || month == 0, 0, "Invalid month value of: " + itos(month) + ".");
// Do this check after month is tested as valid
ERR_FAIL_COND_V_MSG(day > MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1] || day == 0, 0, "Invalid day value of '" + itos(day) + "' which is larger than '" + itos(MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1]) + "' or 0.");
unsigned int days_in_month = MONTH_DAYS_TABLE[LEAPYEAR(year)][month - 1];
ERR_FAIL_COND_V_MSG(day == 0 || day > days_in_month, 0, "Invalid day value of: " + itos(day) + ". It should be comprised between 1 and " + itos(days_in_month) + " for month " + itos(month) + ".");
// Calculate all the seconds from months past in this year
uint64_t SECONDS_FROM_MONTHS_PAST_THIS_YEAR = DAYS_PAST_THIS_YEAR_TABLE[LEAPYEAR(year)][month - 1] * SECONDS_PER_DAY;

View file

@ -550,7 +550,7 @@
<description>
Gets an epoch time value from a dictionary of time values.
[code]datetime[/code] must be populated with the following keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]hour[/code], [code]minute[/code], [code]second[/code].
If the dictionary is empty [code]0[/code] is returned.
If the dictionary is empty [code]0[/code] is returned. If some keys are omitted, they default to the equivalent values for the UNIX epoch timestamp 0 (1970-01-01 at 00:00:00 UTC).
You can pass the output from [method get_datetime_from_unix_time] directly into this function. Daylight Savings Time ([code]dst[/code]), if present, is ignored.
</description>
</method>

View file

@ -27,6 +27,7 @@
<description>
Duplicates the resource, returning a new resource. By default, sub-resources are shared between resource copies for efficiency. This can be changed by passing [code]true[/code] to the [code]subresources[/code] argument which will copy the subresources.
[b]Note:[/b] If [code]subresources[/code] is [code]true[/code], this method will only perform a shallow copy. Nested resources within subresources will not be duplicated and will still be shared.
[b]Note:[/b] When duplicating a resource, only [code]export[/code]ed properties are copied. Other properties will be set to their default value in the new resource.
</description>
</method>
<method name="emit_changed">

View file

@ -17,6 +17,12 @@
<member name="expand" type="bool" setter="set_expand" getter="get_expand" default="false">
If [code]true[/code], the texture stretches to the edges of the node's bounding rectangle using the [member stretch_mode]. If [code]false[/code], the texture will not scale with the node.
</member>
<member name="flip_h" type="bool" setter="set_flip_h" getter="is_flipped_h" default="false">
If [code]true[/code], texture is flipped horizontally.
</member>
<member name="flip_v" type="bool" setter="set_flip_v" getter="is_flipped_v" default="false">
If [code]true[/code], texture is flipped vertically.
</member>
<member name="stretch_mode" type="int" setter="set_stretch_mode" getter="get_stretch_mode" enum="TextureButton.StretchMode" default="0">
Controls the texture's behavior when you resize the node's bounding rectangle, [b]only if[/b] [member expand] is [code]true[/code]. Set it to one of the [enum StretchMode] constants. See the constants to learn more.
</member>

View file

@ -432,7 +432,7 @@ uint64_t DirAccessUnix::get_space_left() {
return 0;
};
return vfs.f_bfree * vfs.f_bsize;
return (uint64_t)vfs.f_bavail * (uint64_t)vfs.f_frsize;
#else
// FIXME: Implement this.
return 0;

View file

@ -173,6 +173,9 @@ void EditorAudioBus::_notification(int p_what) {
bypass->set_icon(get_icon("AudioBusBypass", "EditorIcons"));
bus_options->set_icon(get_icon("GuiTabMenuHl", "EditorIcons"));
audio_value_preview_box->add_color_override("font_color", get_color("font_color", "TooltipLabel"));
audio_value_preview_box->add_style_override("panel", get_stylebox("panel", "TooltipPanel"));
} break;
case NOTIFICATION_MOUSE_EXIT:
case NOTIFICATION_DRAG_END: {
@ -379,15 +382,24 @@ void EditorAudioBus::_show_value(float slider_value) {
db = _normalized_volume_to_scaled_db(slider_value);
}
String text = vformat("%10.1f dB", db);
String text;
if (Math::is_zero_approx(Math::stepify(db, 0.1))) {
// Prevent displaying `-0.0 dB` and show ` 0.0 dB` instead.
// The leading space makes the text visually line up with its positive/negative counterparts.
text = " 0.0 dB";
} else {
// Show an explicit `+` sign if positive.
text = vformat("%+.1f dB", db);
}
// Also set the preview text as a standard Control tooltip.
// This way, it can be seen when the slider is merely hovered (instead of dragged).
slider->set_tooltip(text);
audio_value_preview_label->set_text(text);
Vector2 slider_size = slider->get_size();
Vector2 slider_position = slider->get_global_position();
float left_padding = 5.0f;
float vert_padding = 10.0f;
Vector2 box_position = Vector2(slider_size.x + left_padding, (slider_size.y - vert_padding) * (1.0f - slider->get_value()) - vert_padding);
const Vector2 slider_size = slider->get_size();
const Vector2 slider_position = slider->get_global_position();
const float vert_padding = 10.0f;
const Vector2 box_position = Vector2(slider_size.x, (slider_size.y - vert_padding) * (1.0f - slider->get_value()) - vert_padding);
audio_value_preview_box->set_position(slider_position + box_position);
audio_value_preview_box->set_size(audio_value_preview_label->get_size());
if (slider->has_focus() && !audio_value_preview_box->is_visible()) {
@ -818,7 +830,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
bus_options = memnew(MenuButton);
bus_options->set_h_size_flags(SIZE_SHRINK_END);
bus_options->set_anchor(MARGIN_RIGHT, 0.0);
bus_options->set_tooltip(TTR("Bus options"));
bus_options->set_tooltip(TTR("Bus Options"));
hbc->add_child(bus_options);
Ref<StyleBoxEmpty> sbempty = memnew(StyleBoxEmpty);
@ -853,14 +865,13 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
audio_value_preview_label->set_v_size_flags(SIZE_EXPAND_FILL);
audio_value_preview_label->set_h_size_flags(SIZE_EXPAND_FILL);
audio_value_preview_label->set_mouse_filter(MOUSE_FILTER_PASS);
audio_value_preview_box->add_color_override("font_color", get_color("font_color", "TooltipLabel"));
audioprev_hbc->add_child(audio_value_preview_label);
slider->add_child(audio_value_preview_box);
audio_value_preview_box->set_as_toplevel(true);
Ref<StyleBoxFlat> panel_style = memnew(StyleBoxFlat);
panel_style->set_bg_color(Color(0.0f, 0.0f, 0.0f, 0.8f));
audio_value_preview_box->add_style_override("panel", panel_style);
audio_value_preview_box->add_style_override("panel", get_stylebox("panel", "TooltipPanel"));
audio_value_preview_box->set_mouse_filter(MOUSE_FILTER_PASS);
audio_value_preview_box->hide();
@ -1427,7 +1438,7 @@ void EditorAudioMeterNotches::_bind_methods() {
void EditorAudioMeterNotches::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
notch_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1, 1, 1) : Color(0, 0, 0);
notch_color = get_color("font_color", "Editor");
} break;
case NOTIFICATION_DRAW: {
_draw_audio_notches();
@ -1442,13 +1453,13 @@ void EditorAudioMeterNotches::_draw_audio_notches() {
for (int i = 0; i < notches.size(); i++) {
AudioNotch n = notches[i];
draw_line(Vector2(0, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
Vector2(line_length, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
Vector2(line_length * EDSCALE, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
notch_color,
1);
Math::round(EDSCALE));
if (n.render_db_value) {
draw_string(font,
Vector2(line_length + label_space,
Vector2((line_length + label_space) * EDSCALE,
(1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + (font_height / 4) + top_padding),
String::num(Math::abs(n.db_value)) + "dB",
notch_color);
@ -1456,10 +1467,6 @@ void EditorAudioMeterNotches::_draw_audio_notches() {
}
}
EditorAudioMeterNotches::EditorAudioMeterNotches() :
line_length(5.0f),
label_space(2.0f),
btm_padding(9.0f),
top_padding(5.0f) {
notch_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1, 1, 1) : Color(0, 0, 0);
EditorAudioMeterNotches::EditorAudioMeterNotches() {
notch_color = get_color("font_color", "Editor");
}

View file

@ -244,10 +244,10 @@ private:
List<AudioNotch> notches;
public:
float line_length;
float label_space;
float btm_padding;
float top_padding;
const float line_length = 5.0f;
const float label_space = 2.0f;
const float btm_padding = 9.0f;
const float top_padding = 5.0f;
Color notch_color;
void add_notch(float p_normalized_offset, float p_db_value, bool p_render_value = false);

View file

@ -116,6 +116,18 @@ bool EditorFeatureProfile::has_class_properties_disabled(const StringName &p_cla
return disabled_properties.has(p_class);
}
void EditorFeatureProfile::set_item_collapsed(const StringName &p_class, bool p_collapsed) {
if (p_collapsed) {
collapsed_classes.insert(p_class);
} else {
collapsed_classes.erase(p_class);
}
}
bool EditorFeatureProfile::is_item_collapsed(const StringName &p_class) const {
return collapsed_classes.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;
@ -478,6 +490,9 @@ void EditorFeatureProfileManager::_fill_classes_from(TreeItem *p_parent, const S
class_item->set_selectable(0, true);
class_item->set_metadata(0, p_class);
bool collapsed = edited->is_item_collapsed(p_class);
class_item->set_collapsed(collapsed);
if (p_class == p_selected) {
class_item->select(0);
}
@ -590,6 +605,26 @@ void EditorFeatureProfileManager::_class_list_item_edited() {
}
}
void EditorFeatureProfileManager::_class_list_item_collapsed(Object *p_item) {
if (updating_features) {
return;
}
TreeItem *item = Object::cast_to<TreeItem>(p_item);
if (!item) {
return;
}
Variant md = item->get_metadata(0);
if (md.get_type() != Variant::STRING) {
return;
}
String class_name = md;
bool collapsed = item->is_collapsed();
edited->set_item_collapsed(class_name, collapsed);
}
void EditorFeatureProfileManager::_property_item_edited() {
if (updating_features) {
return;
@ -781,6 +816,7 @@ void EditorFeatureProfileManager::_bind_methods() {
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("_class_list_item_collapsed", &EditorFeatureProfileManager::_class_list_item_collapsed);
ClassDB::bind_method("_property_item_edited", &EditorFeatureProfileManager::_property_item_edited);
ClassDB::bind_method("_emit_current_profile_changed", &EditorFeatureProfileManager::_emit_current_profile_changed);
@ -852,6 +888,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
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);
class_list->connect("item_collapsed", this, "_class_list_item_collapsed");
VBoxContainer *property_list_vbc = memnew(VBoxContainer);
h_split->add_child(property_list_vbc);

View file

@ -60,6 +60,8 @@ private:
Set<StringName> disabled_editors;
Map<StringName, Set<StringName>> disabled_properties;
Set<StringName> collapsed_classes;
bool features_disabled[FEATURE_MAX];
static const char *feature_names[FEATURE_MAX];
static const char *feature_identifiers[FEATURE_MAX];
@ -80,6 +82,9 @@ public:
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_item_collapsed(const StringName &p_class, bool p_collapsed);
bool is_item_collapsed(const StringName &p_class) const;
void set_disable_feature(Feature p_feature, bool p_disable);
bool is_feature_disabled(Feature p_feature) const;
@ -148,6 +153,7 @@ class EditorFeatureProfileManager : public AcceptDialog {
void _class_list_item_selected();
void _class_list_item_edited();
void _class_list_item_collapsed(Object *p_item);
void _property_item_edited();
void _save_and_update();

View file

@ -209,6 +209,7 @@ PluginConfigDialog::PluginConfigDialog() {
desc_edit = memnew(TextEdit);
desc_edit->set_custom_minimum_size(Size2(400, 80) * EDSCALE);
desc_edit->set_wrap_enabled(true);
grid->add_child(desc_edit);
Label *author_lb = memnew(Label);

View file

@ -5252,8 +5252,10 @@ void CanvasItemEditor::_bind_methods() {
ClassDB::bind_method("_popup_warning_depop", &CanvasItemEditor::_popup_warning_depop);
ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed);
ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide);
ClassDB::bind_method(D_METHOD("get_state"), &CanvasItemEditor::get_state);
ClassDB::bind_method(D_METHOD("set_state"), &CanvasItemEditor::set_state);
ClassDB::bind_method(D_METHOD("update_viewport"), &CanvasItemEditor::update_viewport);
ClassDB::bind_method(D_METHOD("_zoom_on_position"), &CanvasItemEditor::_zoom_on_position);
ADD_SIGNAL(MethodInfo("item_lock_status_changed"));
ADD_SIGNAL(MethodInfo("item_group_status_changed"));

View file

@ -31,6 +31,7 @@
#include "script_text_editor.h"
#include "core/math/expression.h"
#include "core/os/input.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
@ -1506,11 +1507,17 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
Array files = d["files"];
String text_to_drop;
bool preload = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
for (int i = 0; i < files.size(); i++) {
if (i > 0) {
text_to_drop += ",";
text_to_drop += ", ";
}
if (preload) {
text_to_drop += "preload(\"" + String(files[i]).c_escape() + "\")";
} else {
text_to_drop += "\"" + String(files[i]).c_escape() + "\"";
}
text_to_drop += "\"" + String(files[i]).c_escape() + "\"";
}
te->cursor_set_line(row);

View file

@ -247,7 +247,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
OTHER_LDFLAGS = "$linker_flags";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
TARGETED_DEVICE_FAMILY = "$targeted_device_family";
};
name = Debug;
};
@ -286,7 +286,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
OTHER_LDFLAGS = "$linker_flags";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
TARGETED_DEVICE_FAMILY = "$targeted_device_family";
VALIDATE_PRODUCT = YES;
};
name = Release;
@ -315,7 +315,7 @@
PRODUCT_BUNDLE_IDENTIFIER = $identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "$provisioning_profile_uuid_debug";
TARGETED_DEVICE_FAMILY = "1,2";
TARGETED_DEVICE_FAMILY = "$targeted_device_family";
VALID_ARCHS = "armv7 armv7s arm64 i386 x86_64";
WRAPPER_EXTENSION = app;
};
@ -345,7 +345,7 @@
PRODUCT_BUNDLE_IDENTIFIER = $identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "$provisioning_profile_uuid_release";
TARGETED_DEVICE_FAMILY = "1,2";
TARGETED_DEVICE_FAMILY = "$targeted_device_family";
VALID_ARCHS = "armv7 armv7s arm64 i386 x86_64";
WRAPPER_EXTENSION = app;
};

View file

@ -23,7 +23,7 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
buildConfiguration = "$default_build_config"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
@ -42,7 +42,7 @@
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "$default_build_config"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
@ -67,7 +67,7 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Debug"
buildConfiguration = "$default_build_config"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
@ -84,10 +84,10 @@
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
buildConfiguration = "$default_build_config">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Debug"
buildConfiguration = "$default_build_config"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View file

@ -203,6 +203,8 @@ ScriptInstance *PluginScript::instance_create(Object *p_this) {
}
bool PluginScript::instance_has(const Object *p_this) const {
ERR_FAIL_COND_V(!_language, false);
_language->lock();
bool hasit = _instances.has((Object *)p_this);
_language->unlock();

View file

@ -31,6 +31,9 @@
<member name="noise" type="OpenSimplexNoise" setter="set_noise" getter="get_noise">
The [OpenSimplexNoise] instance used to generate the noise.
</member>
<member name="noise_offset" type="Vector2" setter="set_noise_offset" getter="get_noise_offset" default="Vector2( 0, 0 )">
An offset used to specify the noise space coordinate of the top left corner of the generated noise. This value is ignored if [member seamless] is enabled.
</member>
<member name="seamless" type="bool" setter="set_seamless" getter="get_seamless" default="false">
Whether the texture can be tiled without visible seams or not. Seamless textures take longer to generate.
[b]Note:[/b] Seamless noise has a lower contrast compared to non-seamless noise. This is due to the way noise uses higher dimensions for generating seamless noise.

View file

@ -31,8 +31,10 @@
</argument>
<argument index="1" name="height" type="int">
</argument>
<argument index="2" name="noise_offset" type="Vector2" default="Vector2( 0, 0 )">
</argument>
<description>
Generate a noise image in [constant Image.FORMAT_L8] format with the requested [code]width[/code] and [code]height[/code], based on the current noise parameters.
Generate a noise image in [constant Image.FORMAT_L8] format with the requested [code]width[/code] and [code]height[/code], based on the current noise parameters. If [code]noise_offset[/code] is specified, then the offset value is used as the coordinates of the top-left corner of the generated noise.
</description>
</method>
<method name="get_noise_1d" qualifiers="const">

View file

@ -62,6 +62,9 @@ void NoiseTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise);
ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise);
ClassDB::bind_method(D_METHOD("set_noise_offset", "noise_offset"), &NoiseTexture::set_noise_offset);
ClassDB::bind_method(D_METHOD("get_noise_offset"), &NoiseTexture::get_noise_offset);
ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture::set_seamless);
ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless);
@ -82,6 +85,7 @@ void NoiseTexture::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "as_normalmap"), "set_as_normalmap", "is_normalmap");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bump_strength", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater"), "set_bump_strength", "get_bump_strength");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "noise_offset"), "set_noise_offset", "get_noise_offset");
}
void NoiseTexture::_validate_property(PropertyInfo &property) const {
@ -137,7 +141,7 @@ Ref<Image> NoiseTexture::_generate_texture() {
if (seamless) {
image = ref_noise->get_seamless_image(size.x);
} else {
image = ref_noise->get_image(size.x, size.y);
image = ref_noise->get_image(size.x, size.y, noise_offset);
}
if (as_normalmap) {
@ -205,6 +209,14 @@ void NoiseTexture::set_height(int p_height) {
_queue_update();
}
void NoiseTexture::set_noise_offset(Vector2 p_noise_offset) {
if (noise_offset == p_noise_offset) {
return;
}
noise_offset = p_noise_offset;
_queue_update();
}
void NoiseTexture::set_seamless(bool p_seamless) {
if (p_seamless == seamless) {
return;
@ -252,6 +264,10 @@ int NoiseTexture::get_height() const {
return size.y;
}
Vector2 NoiseTexture::get_noise_offset() const {
return noise_offset;
}
void NoiseTexture::set_flags(uint32_t p_flags) {
flags = p_flags;
VS::get_singleton()->texture_set_flags(texture, flags);

View file

@ -56,6 +56,7 @@ private:
Ref<OpenSimplexNoise> noise;
Vector2i size;
Vector2 noise_offset;
bool seamless;
bool as_normalmap;
float bump_strength;
@ -79,6 +80,9 @@ public:
void set_width(int p_width);
void set_height(int p_height);
void set_noise_offset(Vector2 p_noise_offset);
Vector2 get_noise_offset() const;
void set_seamless(bool p_seamless);
bool get_seamless();

View file

@ -102,7 +102,7 @@ void OpenSimplexNoise::set_lacunarity(float p_lacunarity) {
emit_changed();
}
Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height) const {
Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height, const Vector2 &p_noise_offset) const {
PoolVector<uint8_t> data;
data.resize(p_width * p_height);
@ -110,7 +110,7 @@ Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height) const {
for (int i = 0; i < p_height; i++) {
for (int j = 0; j < p_width; j++) {
float v = get_noise_2d(i, j);
float v = get_noise_2d(float(j) + p_noise_offset.x, float(i) + p_noise_offset.y);
v = v * 0.5 + 0.5; // Normalize [0..1]
wd8[(i * p_width + j)] = uint8_t(CLAMP(v * 255.0, 0, 255));
}
@ -167,7 +167,7 @@ void OpenSimplexNoise::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lacunarity", "lacunarity"), &OpenSimplexNoise::set_lacunarity);
ClassDB::bind_method(D_METHOD("get_lacunarity"), &OpenSimplexNoise::get_lacunarity);
ClassDB::bind_method(D_METHOD("get_image", "width", "height"), &OpenSimplexNoise::get_image);
ClassDB::bind_method(D_METHOD("get_image", "width", "height", "noise_offset"), &OpenSimplexNoise::get_image, DEFVAL(Vector2()));
ClassDB::bind_method(D_METHOD("get_seamless_image", "size"), &OpenSimplexNoise::get_seamless_image);
ClassDB::bind_method(D_METHOD("get_noise_1d", "x"), &OpenSimplexNoise::get_noise_1d);

View file

@ -75,7 +75,7 @@ public:
void set_lacunarity(float p_lacunarity);
float get_lacunarity() const { return lacunarity; }
Ref<Image> get_image(int p_width, int p_height) const;
Ref<Image> get_image(int p_width, int p_height, const Vector2 &p_noise_offset = Vector2()) const;
Ref<Image> get_seamless_image(int p_size) const;
float get_noise_1d(float x) const;

View file

@ -134,6 +134,7 @@ bool VisualScriptBuiltinFunc::has_input_sequence_port() const {
case TEXT_PRINT:
case TEXT_PRINTERR:
case TEXT_PRINTRAW:
case MATH_SEED:
return true;
default:
return false;

View file

@ -352,6 +352,8 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_release", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Distribution"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_release", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/targeted_device_family", PROPERTY_HINT_ENUM, "iPhone,iPad,iPhone & iPad"), 2));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
@ -444,6 +446,8 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n";
} else if (lines[i].find("$team_id") != -1) {
strnew += lines[i].replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n";
} else if (lines[i].find("$default_build_config") != -1) {
strnew += lines[i].replace("$default_build_config", p_debug ? "Debug" : "Release") + "\n";
} else if (lines[i].find("$export_method") != -1) {
int export_method = p_preset->get(p_debug ? "application/export_method_debug" : "application/export_method_release");
strnew += lines[i].replace("$export_method", export_method_string[export_method]) + "\n";
@ -464,6 +468,20 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$godot_archs", p_config.architectures) + "\n";
} else if (lines[i].find("$linker_flags") != -1) {
strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n";
} else if (lines[i].find("$targeted_device_family") != -1) {
String xcode_value;
switch ((int)p_preset->get("application/targeted_device_family")) {
case 0: // iPhone
xcode_value = "1";
break;
case 1: // iPad
xcode_value = "2";
break;
case 2: // iPhone & iPad
xcode_value = "1,2";
break;
}
strnew += lines[i].replace("$targeted_device_family", xcode_value) + "\n";
} else if (lines[i].find("$cpp_code") != -1) {
strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n";
} else if (lines[i].find("$docs_in_place") != -1) {

View file

@ -272,11 +272,10 @@ void Camera2D::_notification(int p_what) {
}
if (screen_drawing_enabled) {
Color area_axis_color(0.5, 0.42, 0.87, 0.63);
Color area_axis_color(1, 0.4, 1, 0.63);
float area_axis_width = 1;
if (is_current()) {
area_axis_width = 3;
area_axis_color.a = 0.83;
}
Transform2D inv_camera_transform = get_camera_transform().affine_inverse();
@ -297,10 +296,9 @@ void Camera2D::_notification(int p_what) {
}
if (limit_drawing_enabled) {
Color limit_drawing_color(1, 1, 0, 0.63);
Color limit_drawing_color(1, 1, 0.25, 0.63);
float limit_drawing_width = 1;
if (is_current()) {
limit_drawing_color.a = 0.83;
limit_drawing_width = 3;
}
@ -319,11 +317,10 @@ void Camera2D::_notification(int p_what) {
}
if (margin_drawing_enabled) {
Color margin_drawing_color(0, 1, 1, 0.63);
Color margin_drawing_color(0.25, 1, 1, 0.63);
float margin_drawing_width = 1;
if (is_current()) {
margin_drawing_width = 3;
margin_drawing_color.a = 0.83;
}
Transform2D inv_camera_transform = get_camera_transform().affine_inverse();

View file

@ -666,7 +666,7 @@ void Skeleton::_rebuild_physical_bones_cache() {
const int b_size = bones.size();
for (int i = 0; i < b_size; ++i) {
PhysicalBone *parent_pb = _get_physical_bone_parent(i);
if (parent_pb != bones[i].physical_bone) {
if (parent_pb != bones[i].cache_parent_physical_bone) {
bones.write[i].cache_parent_physical_bone = parent_pb;
if (bones[i].physical_bone) {
bones[i].physical_bone->_on_bone_parent_changed();

View file

@ -32,6 +32,12 @@
#include "core/method_bind_ext.gen.inc"
struct _MinSizeCache {
int min_size;
bool will_stretch;
int final_size;
};
bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
if (!p_name.operator String().begins_with("slot/")) {
return false;
@ -119,15 +125,23 @@ void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const {
}
void GraphNode::_resort() {
int sep = get_constant("separation");
Ref<StyleBox> sb = get_stylebox("frame");
bool first = true;
/** First pass, determine minimum size AND amount of stretchable elements */
Size2 minsize;
Size2 new_size = get_size();
Ref<StyleBox> sb = get_stylebox("frame");
int sep = get_constant("separation");
bool first = true;
int children_count = 0;
int stretch_min = 0;
int stretch_avail = 0;
float stretch_ratio_total = 0;
Map<Control *, _MinSizeCache> min_size_cache;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
if (!c) {
if (!c || !c->is_visible_in_tree()) {
continue;
}
if (c->is_set_as_toplevel()) {
@ -135,38 +149,120 @@ void GraphNode::_resort() {
}
Size2i size = c->get_combined_minimum_size();
_MinSizeCache msc;
minsize.y += size.y;
minsize.x = MAX(minsize.x, size.x);
stretch_min += size.height;
msc.min_size = size.height;
msc.will_stretch = c->get_v_size_flags() & SIZE_EXPAND;
if (msc.will_stretch) {
stretch_avail += msc.min_size;
stretch_ratio_total += c->get_stretch_ratio();
}
msc.final_size = msc.min_size;
min_size_cache[c] = msc;
children_count++;
}
if (children_count == 0) {
return;
}
int stretch_max = new_size.height - (children_count - 1) * sep;
int stretch_diff = stretch_max - stretch_min;
if (stretch_diff < 0) {
//avoid negative stretch space
stretch_diff = 0;
}
stretch_avail += stretch_diff - sb->get_margin(MARGIN_BOTTOM) - sb->get_margin(MARGIN_TOP); //available stretch space.
/** Second, pass sucessively to discard elements that can't be stretched, this will run while stretchable
elements exist */
while (stretch_ratio_total > 0) { // first of all, don't even be here if no stretchable objects exist
bool refit_successful = true; //assume refit-test will go well
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
if (!c || !c->is_visible_in_tree()) {
continue;
}
if (c->is_set_as_toplevel()) {
continue;
}
ERR_FAIL_COND(!min_size_cache.has(c));
_MinSizeCache &msc = min_size_cache[c];
if (msc.will_stretch) { //wants to stretch
//let's see if it can really stretch
int final_pixel_size = stretch_avail * c->get_stretch_ratio() / stretch_ratio_total;
if (final_pixel_size < msc.min_size) {
//if available stretching area is too small for widget,
//then remove it from stretching area
msc.will_stretch = false;
stretch_ratio_total -= c->get_stretch_ratio();
refit_successful = false;
stretch_avail -= msc.min_size;
msc.final_size = msc.min_size;
break;
} else {
msc.final_size = final_pixel_size;
}
}
}
if (refit_successful) { //uf refit went well, break
break;
}
}
/** Final pass, draw and stretch elements **/
int ofs = sb->get_margin(MARGIN_TOP);
first = true;
int idx = 0;
cache_y.clear();
int w = new_size.width - sb->get_minimum_size().x;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
if (!c || !c->is_visible_in_tree()) {
continue;
}
if (c->is_set_as_toplevel()) {
continue;
}
_MinSizeCache &msc = min_size_cache[c];
if (first) {
first = false;
} else {
minsize.y += sep;
}
}
int vofs = 0;
int w = get_size().x - sb->get_minimum_size().x;
cache_y.clear();
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
if (!c) {
continue;
}
if (c->is_set_as_toplevel()) {
continue;
ofs += sep;
}
Size2i size = c->get_combined_minimum_size();
int from = ofs;
int to = ofs + msc.final_size;
Rect2 r(sb->get_margin(MARGIN_LEFT), sb->get_margin(MARGIN_TOP) + vofs, w, size.y);
if (msc.will_stretch && idx == children_count - 1) {
//adjust so the last one always fits perfect
//compensating for numerical imprecision
fit_child_in_rect(c, r);
cache_y.push_back(vofs + size.y * 0.5);
to = new_size.height - sb->get_margin(MARGIN_BOTTOM);
}
vofs += size.y + sep;
int size = to - from;
Rect2 rect(sb->get_margin(MARGIN_LEFT), from, w, size);
fit_child_in_rect(c, rect);
cache_y.push_back(from - sb->get_margin(MARGIN_TOP) + size * 0.5);
ofs = to;
idx++;
}
update();

View file

@ -166,9 +166,11 @@ void TextureButton::_notification(int p_what) {
} break;
}
Point2 ofs;
Size2 size;
if (texdraw.is_valid()) {
Point2 ofs;
Size2 size = texdraw->get_size();
size = texdraw->get_size();
_texture_region = Rect2(Point2(), texdraw->get_size());
_tile = false;
if (expand) {
@ -218,17 +220,21 @@ void TextureButton::_notification(int p_what) {
}
_position_rect = Rect2(ofs, size);
size.width *= hflip ? -1.0f : 1.0f;
size.height *= vflip ? -1.0f : 1.0f;
if (_tile) {
draw_texture_rect(texdraw, _position_rect, _tile);
draw_texture_rect(texdraw, Rect2(ofs, size), _tile);
} else {
draw_texture_rect_region(texdraw, _position_rect, _texture_region);
draw_texture_rect_region(texdraw, Rect2(ofs, size), _texture_region);
}
} else {
_position_rect = Rect2();
}
if (has_focus() && focused.is_valid()) {
draw_texture_rect(focused, _position_rect, false);
draw_texture_rect(focused, Rect2(ofs, size), false);
};
} break;
}
@ -243,6 +249,10 @@ void TextureButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_click_mask", "mask"), &TextureButton::set_click_mask);
ClassDB::bind_method(D_METHOD("set_expand", "p_expand"), &TextureButton::set_expand);
ClassDB::bind_method(D_METHOD("set_stretch_mode", "p_mode"), &TextureButton::set_stretch_mode);
ClassDB::bind_method(D_METHOD("set_flip_h", "enable"), &TextureButton::set_flip_h);
ClassDB::bind_method(D_METHOD("is_flipped_h"), &TextureButton::is_flipped_h);
ClassDB::bind_method(D_METHOD("set_flip_v", "enable"), &TextureButton::set_flip_v);
ClassDB::bind_method(D_METHOD("is_flipped_v"), &TextureButton::is_flipped_v);
ClassDB::bind_method(D_METHOD("get_normal_texture"), &TextureButton::get_normal_texture);
ClassDB::bind_method(D_METHOD("get_pressed_texture"), &TextureButton::get_pressed_texture);
@ -262,6 +272,8 @@ void TextureButton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_click_mask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_click_mask", "get_click_mask");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_expand", "get_expand");
ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_flip_h", "is_flipped_h");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_flip_v", "is_flipped_v");
BIND_ENUM_CONSTANT(STRETCH_SCALE);
BIND_ENUM_CONSTANT(STRETCH_TILE);
@ -338,9 +350,29 @@ TextureButton::StretchMode TextureButton::get_stretch_mode() const {
return stretch_mode;
}
void TextureButton::set_flip_h(bool p_flip) {
hflip = p_flip;
update();
}
bool TextureButton::is_flipped_h() const {
return hflip;
}
void TextureButton::set_flip_v(bool p_flip) {
vflip = p_flip;
update();
}
bool TextureButton::is_flipped_v() const {
return vflip;
}
TextureButton::TextureButton() {
expand = false;
stretch_mode = STRETCH_SCALE;
hflip = false;
vflip = false;
_texture_region = Rect2();
_position_rect = Rect2();

View file

@ -61,6 +61,9 @@ private:
Rect2 _position_rect;
bool _tile;
bool hflip;
bool vflip;
protected:
virtual Size2 get_minimum_size() const;
virtual bool has_point(const Point2 &p_point) const;
@ -88,6 +91,12 @@ public:
void set_stretch_mode(StretchMode p_stretch_mode);
StretchMode get_stretch_mode() const;
void set_flip_h(bool p_flip);
bool is_flipped_h() const;
void set_flip_v(bool p_flip);
bool is_flipped_v() const;
TextureButton();
};

View file

@ -322,17 +322,19 @@ bool HTTPRequest::_update_connection() {
}
PoolByteArray chunk = client->read_response_body_chunk();
downloaded.add(chunk.size());
if (file) {
PoolByteArray::Read r = chunk.read();
file->store_buffer(r.ptr(), chunk.size());
if (file->get_error() != OK) {
call_deferred("_request_done", RESULT_DOWNLOAD_FILE_WRITE_ERROR, response_code, response_headers, PoolByteArray());
return true;
if (chunk.size()) {
downloaded.add(chunk.size());
if (file) {
PoolByteArray::Read r = chunk.read();
file->store_buffer(r.ptr(), chunk.size());
if (file->get_error() != OK) {
call_deferred("_request_done", RESULT_DOWNLOAD_FILE_WRITE_ERROR, response_code, response_headers, PoolByteArray());
return true;
}
} else {
body.append_array(chunk);
}
} else {
body.append_array(chunk);
}
if (body_size_limit >= 0 && downloaded.get() > body_size_limit) {

View file

@ -65,17 +65,19 @@ void BodySW::update_inertias() {
// We have to recompute the center of mass.
center_of_mass_local.zero();
for (int i = 0; i < get_shape_count(); i++) {
real_t area = get_shape_area(i);
if (total_area != 0.0) {
for (int i = 0; i < get_shape_count(); i++) {
real_t area = get_shape_area(i);
real_t mass = area * this->mass / total_area;
real_t mass = area * this->mass / total_area;
// NOTE: we assume that the shape origin is also its center of mass.
center_of_mass_local += mass * get_shape_transform(i).origin;
// NOTE: we assume that the shape origin is also its center of mass.
center_of_mass_local += mass * get_shape_transform(i).origin;
}
center_of_mass_local /= mass;
}
center_of_mass_local /= mass;
// Recompute the inertia tensor.
Basis inertia_tensor;
inertia_tensor.set_zero();
@ -86,12 +88,15 @@ void BodySW::update_inertias() {
continue;
}
real_t area = get_shape_area(i);
if (area == 0.0) {
continue;
}
inertia_set = true;
const ShapeSW *shape = get_shape(i);
real_t area = get_shape_area(i);
real_t mass = area * this->mass / total_area;
Basis shape_inertia_tensor = shape->get_moment_of_inertia(mass).to_diagonal_matrix();