Merge pull request #33569 from akien-mga/3.1

Assorted cherry-picks from the master branch for Godot 3.1.2 [4th batch]
This commit is contained in:
Rémi Verschelde 2019-11-12 15:45:30 +01:00 committed by GitHub
commit 7f6e2c5037
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
395 changed files with 15990 additions and 8841 deletions

View File

@ -165,7 +165,7 @@ License: FTL
Files: ./thirdparty/glad/
Comment: glad
Copyright: 2013-2018, David Herberth
Copyright: 2013-2019, David Herberth
License: Expat
Files: ./thirdparty/jpeg_compressor/
@ -321,7 +321,7 @@ License: BSD-3-clause
Files: ./thirdparty/misc/stb_truetype.h
./thirdparty/misc/stb_vorbis.c
Comment: stb libraries
Copyright: 2007-2017, Sean Barrett
Copyright: 2007-2019, Sean Barrett
License: public-domain
Files: ./thirdparty/misc/triangulator.cpp
@ -350,8 +350,8 @@ License: BSD-3-clause
Files: ./thirdparty/pcre2/
Comment: PCRE2
Copyright: 1997-2018, University of Cambridge,
2009-2018, Zoltan Herczeg
Copyright: 1997-2019, University of Cambridge,
2009-2019, Zoltan Herczeg
License: BSD-3-clause
Files: ./thirdparty/pvrtccompressor/
@ -371,7 +371,7 @@ License: Expat
Files: ./thirdparty/tinyexr/
Comment: TinyEXR
Copyright: 2014-2018, Syoyo Fujita
Copyright: 2014-2019, Syoyo Fujita
2002, Industrial Light & Magic, a division of Lucas Digital Ltd. LLC
License: BSD-3-clause

View File

@ -121,6 +121,8 @@ if env['builtin_zstd']:
"compress/zstd_ldm.c",
"compress/zstd_opt.c",
"compress/zstdmt_compress.c",
"compress/zstd_compress_literals.c",
"compress/zstd_compress_sequences.c",
"decompress/huf_decompress.c",
"decompress/zstd_ddict.c",
"decompress/zstd_decompress_block.c",

View File

@ -346,6 +346,12 @@ Error HTTPClient::poll() {
} else {
// We are already handshaking, which means we can use your already active SSL connection
ssl = static_cast<Ref<StreamPeerSSL> >(connection);
if (ssl.is_null()) {
close();
status = STATUS_SSL_HANDSHAKE_ERROR;
return ERR_CANT_CONNECT;
}
ssl->poll(); // Try to finish the handshake
}

View File

@ -1230,11 +1230,15 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
buf += 4;
PoolVector<uint8_t>::Read r = data.read();
copymem(buf, &r[0], datalen * datasize);
buf += datalen * datasize;
}
r_len += 4 + datalen * datasize;
while (r_len % 4)
while (r_len % 4) {
r_len++;
if (buf)
*(buf++) = 0;
}
} break;
case Variant::POOL_INT_ARRAY: {

View File

@ -283,8 +283,9 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_
rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_name);
}
ERR_EXPLAIN("RPC '" + String(p_name) + "' is not allowed from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
ERR_FAIL_COND(!_can_call_mode(p_node, rpc_mode, p_from));
bool can_call = _can_call_mode(p_node, rpc_mode, p_from);
ERR_EXPLAIN("RPC '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
ERR_FAIL_COND(!can_call);
int argc = p_packet[p_offset];
Vector<Variant> args;
@ -332,8 +333,9 @@ void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p
rset_mode = p_node->get_script_instance()->get_rset_mode(p_name);
}
ERR_EXPLAIN("RSET '" + String(p_name) + "' is not allowed from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
ERR_FAIL_COND(!_can_call_mode(p_node, rset_mode, p_from));
bool can_call = _can_call_mode(p_node, rset_mode, p_from);
ERR_EXPLAIN("RSET '" + String(p_name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
ERR_FAIL_COND(!can_call);
Variant value;
Error err = decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset, NULL, allow_object_decoding || network_peer->is_object_decoding_allowed());

View File

@ -702,9 +702,11 @@ public:
/* if we can assume that the line segment starts outside the circle (e.g. for continuous time collision detection) then the following can be skipped and we can just return the equivalent of res1 */
sqrtterm = Math::sqrt(sqrtterm);
real_t res1 = (-b - sqrtterm) / (2 * a);
//real_t res2 = ( -b + sqrtterm ) / (2 * a);
real_t res2 = (-b + sqrtterm) / (2 * a);
return (res1 >= 0 && res1 <= 1) ? res1 : -1;
if (res1 >= 0 && res1 <= 1) return res1;
if (res2 >= 0 && res2 <= 1) return res2;
return -1;
}
static inline Vector<Vector3> clip_polygon(const Vector<Vector3> &polygon, const Plane &p_plane) {

View File

@ -218,12 +218,8 @@ Vector3 Vector3::linear_interpolate(const Vector3 &p_b, real_t p_t) const {
}
Vector3 Vector3::slerp(const Vector3 &p_b, real_t p_t) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V(!is_normalized(), Vector3());
#endif
real_t theta = angle_to(p_b);
return rotated(cross(p_b), theta * p_t);
return rotated(cross(p_b).normalized(), theta * p_t);
}
real_t Vector3::distance_to(const Vector3 &p_b) const {

View File

@ -302,10 +302,6 @@ void MessageQueue::flush() {
_call_function(target, message->target, args, message->args, message->type & FLAG_SHOW_ERROR);
for (int i = 0; i < message->args; i++) {
args[i].~Variant();
}
} break;
case TYPE_NOTIFICATION: {
@ -319,11 +315,17 @@ void MessageQueue::flush() {
// messages don't expect a return value
target->set(message->target, *arg);
arg->~Variant();
} break;
}
}
if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) {
Variant *args = (Variant *)(message + 1);
for (int i = 0; i < message->args; i++) {
args[i].~Variant();
}
}
message->~Message();
_THREAD_SAFE_LOCK_

View File

@ -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;
}

View File

@ -779,8 +779,13 @@ public:
static int get_object_count();
_FORCE_INLINE_ static bool instance_validate(Object *p_ptr) {
rw_lock->read_lock();
return instance_checks.has(p_ptr);
bool exists = instance_checks.has(p_ptr);
rw_lock->read_unlock();
return exists;
}
};

View File

@ -90,6 +90,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &Input::action_press, DEFVAL(1.f));
ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release);
ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Input::set_default_cursor_shape, DEFVAL(CURSOR_ARROW));
ClassDB::bind_method(D_METHOD("get_current_cursor_shape"), &Input::get_current_cursor_shape);
ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2()));
ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event);
ClassDB::bind_method(D_METHOD("set_use_accumulated_input", "enable"), &Input::set_use_accumulated_input);

View File

@ -122,10 +122,10 @@ public:
virtual bool is_emulating_touch_from_mouse() const = 0;
virtual bool is_emulating_mouse_from_touch() const = 0;
virtual CursorShape get_default_cursor_shape() = 0;
virtual CursorShape get_default_cursor_shape() const = 0;
virtual void set_default_cursor_shape(CursorShape p_shape) = 0;
virtual CursorShape get_current_cursor_shape() const = 0;
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) = 0;
virtual void set_mouse_in_window(bool p_in_window) = 0;
virtual String get_joy_button_string(int p_button) = 0;
virtual String get_joy_axis_string(int p_axis) = 0;

View File

@ -717,8 +717,17 @@ bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *
bool pressed = same_direction ? Math::abs(jm->get_axis_value()) >= p_deadzone : false;
if (p_pressed != NULL)
*p_pressed = pressed;
if (p_strength != NULL)
*p_strength = pressed ? CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, Math::abs(jm->get_axis_value())), 0.0f, 1.0f) : 0.0f;
if (p_strength != NULL) {
if (pressed) {
if (p_deadzone == 1.0f) {
*p_strength = 1.0f;
} else {
*p_strength = CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, Math::abs(jm->get_axis_value())), 0.0f, 1.0f);
}
} else {
*p_strength = 0.0f;
}
}
}
return match;
}

View File

@ -225,6 +225,16 @@ int OS::get_virtual_keyboard_height() const {
return 0;
}
void OS::set_cursor_shape(CursorShape p_shape) {
}
OS::CursorShape OS::get_cursor_shape() const {
return CURSOR_ARROW;
}
void OS::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
}
void OS::print_all_resources(String p_to_file) {
ERR_FAIL_COND(p_to_file != "" && _OSPRF);

View File

@ -378,8 +378,9 @@ public:
// returns height of the currently shown virtual keyboard (0 if keyboard is hidden)
virtual int get_virtual_keyboard_height() const;
virtual void set_cursor_shape(CursorShape p_shape) = 0;
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) = 0;
virtual void set_cursor_shape(CursorShape p_shape);
virtual CursorShape get_cursor_shape() const;
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
virtual bool get_swap_ok_cancel() { return false; }
virtual void dump_memory_to_file(const char *p_file);

View File

@ -179,6 +179,7 @@ static const char *locale_list[] = {
"ff_SN", // Fulah (Senegal)
"fi", // Finnish
"fi_FI", // Finnish (Finland)
"fil", // Filipino
"fil_PH", // Filipino (Philippines)
"fo_FO", // Faroese (Faroe Islands)
"fr", // French
@ -227,6 +228,7 @@ static const char *locale_list[] = {
"ja", // Japanese
"ja_JP", // Japanese (Japan)
"kab_DZ", // Kabyle (Algeria)
"ka", // Georgian
"ka_GE", // Georgian (Georgia)
"kk_KZ", // Kazakh (Kazakhstan)
"kl_GL", // Kalaallisut (Greenland)
@ -257,10 +259,12 @@ static const char *locale_list[] = {
"mg_MG", // Malagasy (Madagascar)
"mh_MH", // Marshallese (Marshall Islands)
"mhr_RU", // Eastern Mari (Russia)
"mi_NZ", // Maori (New Zealand)
"mi", // Māori
"mi_NZ", // Māori (New Zealand)
"miq_NI", // Mískito (Nicaragua)
"mk", // Macedonian
"mk_MK", // Macedonian (Macedonia)
"ml", // Malayalam
"ml_IN", // Malayalam (India)
"mni_IN", // Manipuri (India)
"mn_MN", // Mongolian (Mongolia)
@ -326,6 +330,7 @@ static const char *locale_list[] = {
"sgs_LT", // Samogitian (Lithuania)
"shs_CA", // Shuswap (Canada)
"sid_ET", // Sidamo (Ethiopia)
"si", // Sinhala
"si_LK", // Sinhala (Sri Lanka)
"sk", // Slovak
"sk_SK", // Slovak (Slovakia)
@ -343,6 +348,7 @@ static const char *locale_list[] = {
"sq_MK", // Albanian (Macedonia)
"sr", // Serbian
"sr_Cyrl", // Serbian (Cyrillic)
"sr_Latn", // Serbian (Latin)
"sr_ME", // Serbian (Montenegro)
"sr_RS", // Serbian (Serbia)
"ss_ZA", // Swati (South Africa)
@ -357,6 +363,7 @@ static const char *locale_list[] = {
"ta_IN", // Tamil (India)
"ta_LK", // Tamil (Sri Lanka)
"tcy_IN", // Tulu (India)
"te", // Telugu
"te_IN", // Telugu (India)
"tg_TJ", // Tajik (Tajikistan)
"the_NP", // Chitwania Tharu (Nepal)
@ -540,6 +547,7 @@ static const char *locale_names[] = {
"Fulah (Senegal)",
"Finnish",
"Finnish (Finland)",
"Filipino",
"Filipino (Philippines)",
"Faroese (Faroe Islands)",
"French",
@ -588,6 +596,7 @@ static const char *locale_names[] = {
"Japanese",
"Japanese (Japan)",
"Kabyle (Algeria)",
"Georgian",
"Georgian (Georgia)",
"Kazakh (Kazakhstan)",
"Kalaallisut (Greenland)",
@ -618,10 +627,12 @@ static const char *locale_names[] = {
"Malagasy (Madagascar)",
"Marshallese (Marshall Islands)",
"Eastern Mari (Russia)",
"Maori (New Zealand)",
"Māori",
"Māori (New Zealand)",
"Mískito (Nicaragua)",
"Macedonian",
"Macedonian (Macedonia)",
"Malayalam",
"Malayalam (India)",
"Manipuri (India)",
"Mongolian (Mongolia)",
@ -687,6 +698,7 @@ static const char *locale_names[] = {
"Samogitian (Lithuania)",
"Shuswap (Canada)",
"Sidamo (Ethiopia)",
"Sinhala",
"Sinhala (Sri Lanka)",
"Slovak",
"Slovak (Slovakia)",
@ -704,6 +716,7 @@ static const char *locale_names[] = {
"Albanian (Macedonia)",
"Serbian",
"Serbian (Cyrillic)",
"Serbian (Latin)",
"Serbian (Montenegro)",
"Serbian (Serbia)",
"Swati (South Africa)",
@ -718,6 +731,7 @@ static const char *locale_names[] = {
"Tamil (India)",
"Tamil (Sri Lanka)",
"Tulu (India)",
"Telugu",
"Telugu (India)",
"Tajik (Tajikistan)",
"Chitwania Tharu (Nepal)",

View File

@ -21,6 +21,12 @@
<description>
</description>
</method>
<method name="_export_end" qualifiers="virtual">
<return type="void">
</return>
<description>
</description>
</method>
<method name="_export_file" qualifiers="virtual">
<return type="void">
</return>

View File

@ -214,14 +214,19 @@
Use with [method set_param], [method set_param_randomness], and [method set_param_texture] to set animation offset properties.
</constant>
<constant name="PARAM_MAX" value="12" enum="Parameter">
Represents the size of the [enum Parameter] enum.
</constant>
<constant name="FLAG_ALIGN_Y_TO_VELOCITY" value="0" enum="Flags">
Use with [method set_flag] to set [member flag_align_y].
</constant>
<constant name="FLAG_ROTATE_Y" value="1" enum="Flags">
Use with [method set_flag] to set [member flag_rotate_y]
Use with [method set_flag] to set [member flag_rotate_y].
</constant>
<constant name="FLAG_DISABLE_Z" value="2" enum="Flags">
Use with [method set_flag] to set [member flag_disable_z].
</constant>
<constant name="FLAG_MAX" value="3" enum="Flags">
Represents the size of the [enum Flags] enum.
</constant>
<constant name="EMISSION_SHAPE_POINT" value="0" enum="EmissionShape">
All particles will be emitted from a single point.

View File

@ -321,6 +321,12 @@
<constant name="HALF_OFFSET_DISABLED" value="2" enum="HalfOffset">
Half offset disabled.
</constant>
<constant name="HALF_OFFSET_NEGATIVE_X" value="3" enum="HalfOffset">
Half offset on the X coordinate (negative).
</constant>
<constant name="HALF_OFFSET_NEGATIVE_Y" value="4" enum="HalfOffset">
Half offset on the Y coordinate (negative).
</constant>
<constant name="TILE_ORIGIN_TOP_LEFT" value="0" enum="TileOrigin">
Tile origin at its top-left corner.
</constant>

View File

@ -1110,8 +1110,8 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
LightInstance *li = light_instance_owner.getornull(e->instance->light_instances[i]);
if (li->light_index >= render_light_instance_count) {
continue; // too many
if (li->light_index >= render_light_instance_count || render_light_instances[li->light_index] != li) {
continue; // too many or light_index did not correspond to the light instances to be rendered
}
if (copy) {

View File

@ -2354,7 +2354,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
if (p_depth_pass) {
if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) || p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER || p_material->shader->spatial.no_depth_test)
if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) || p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER || p_material->shader->spatial.no_depth_test || p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF)
return; //bye
if (!p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {

View File

@ -191,6 +191,14 @@ Error AudioDriverPulseAudio::init_device() {
spec.format = PA_SAMPLE_S16LE;
spec.channels = pa_map.channels;
spec.rate = mix_rate;
pa_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
pa_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
pa_map.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
pa_map.map[3] = PA_CHANNEL_POSITION_LFE;
pa_map.map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
pa_map.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
pa_map.map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
pa_map.map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
pa_str = pa_stream_new(pa_ctx, "Sound", &spec, &pa_map);
if (pa_str == NULL) {

View File

@ -544,7 +544,7 @@ public:
if (use_fps && animation->get_step() > 0) {
float max_frame = animation->get_length() / animation->get_step();
p_list->push_back(PropertyInfo(Variant::REAL, "frame", PROPERTY_HINT_RANGE, "0," + rtos(max_frame) + ",0.01"));
p_list->push_back(PropertyInfo(Variant::REAL, "frame", PROPERTY_HINT_RANGE, "0," + rtos(max_frame) + ",1"));
} else {
p_list->push_back(PropertyInfo(Variant::REAL, "time", PROPERTY_HINT_RANGE, "0," + rtos(animation->get_length()) + ",0.01"));
}
@ -1205,7 +1205,9 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
////////////////////////////////////
void AnimationTrackEdit::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
if (animation.is_null())
return;
ERR_FAIL_INDEX(track, animation->get_track_count());
@ -1241,20 +1243,15 @@ void AnimationTrackEdit::_notification(int p_what) {
int ofs = in_group ? check->get_width() : 0; //not the best reference for margin but..
check_rect = Rect2(Point2(ofs, int(get_size().height - check->get_height()) / 2), check->get_size());
draw_texture(check, check_rect.position);
ofs += check->get_width() + hsep;
Ref<Texture> type_icon = type_icons[animation->track_get_type(track)];
draw_texture(type_icon, Point2(ofs, int(get_size().height - type_icon->get_height()) / 2));
ofs += type_icon->get_width() + hsep;
NodePath path = animation->track_get_path(track);
Node *node = NULL;
if (root && root->has_node(path)) {
node = root->get_node(path);
}
@ -1319,12 +1316,11 @@ void AnimationTrackEdit::_notification(int p_what) {
draw_line(Point2(limit, 0), Point2(limit, get_size().height), linecolor, Math::round(EDSCALE));
}
// KEYFAMES //
// KEYFRAMES //
draw_bg(limit, get_size().width - timeline->get_buttons_width());
{
float scale = timeline->get_zoom_scale();
int limit_end = get_size().width - timeline->get_buttons_width();
@ -1353,6 +1349,7 @@ void AnimationTrackEdit::_notification(int p_what) {
draw_fg(limit, get_size().width - timeline->get_buttons_width());
// BUTTONS //
{
Ref<Texture> wrap_icon[2] = {
@ -1577,7 +1574,18 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool
if (p_x < p_clip_left || p_x > p_clip_right)
return;
Vector2 ofs(p_x - type_icon->get_width() / 2, int(get_size().height - type_icon->get_height()) / 2);
Ref<Texture> icon_to_draw = p_selected ? selected_icon : type_icon;
// Override type icon for invalid value keys, unless selected.
if (!p_selected && animation->track_get_type(track) == Animation::TYPE_VALUE) {
const Variant &v = animation->track_get_key_value(track, p_index);
Variant::Type valid_type = Variant::NIL;
if (!_is_value_key_valid(v, valid_type)) {
icon_to_draw = get_icon("KeyInvalid", "EditorIcons");
}
}
Vector2 ofs(p_x - icon_to_draw->get_width() / 2, int(get_size().height - icon_to_draw->get_height()) / 2);
if (animation->track_get_type(track) == Animation::TYPE_METHOD) {
Ref<Font> font = get_font("font", "Label");
@ -1601,16 +1609,13 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool
}
text += ")";
int limit = MAX(0, p_clip_right - p_x - type_icon->get_width());
int limit = MAX(0, p_clip_right - p_x - icon_to_draw->get_width());
if (limit > 0) {
draw_string(font, Vector2(p_x + type_icon->get_width(), int(get_size().height - font->get_height()) / 2 + font->get_ascent()), text, color, limit);
draw_string(font, Vector2(p_x + icon_to_draw->get_width(), int(get_size().height - font->get_height()) / 2 + font->get_ascent()), text, color, limit);
}
}
if (p_selected) {
draw_texture(selected_icon, ofs);
} else {
draw_texture(type_icon, ofs);
}
draw_texture(icon_to_draw, ofs);
}
//helper
@ -1775,6 +1780,27 @@ void AnimationTrackEdit::_path_entered(const String &p_text) {
undo_redo->commit_action();
}
bool AnimationTrackEdit::_is_value_key_valid(const Variant &p_key_value, Variant::Type &r_valid_type) const {
RES res;
Vector<StringName> leftover_path;
Node *node = root->get_node_and_resource(animation->track_get_path(track), res, leftover_path);
Object *obj = NULL;
if (res.is_valid()) {
obj = res.ptr();
} else if (node) {
obj = node;
}
bool prop_exists = false;
if (obj) {
r_valid_type = obj->get_static_property_type_indexed(leftover_path, &prop_exists);
}
return (!prop_exists || Variant::can_convert(p_key_value.get_type(), r_valid_type));
}
String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
if (check_rect.has_point(p_pos)) {
@ -1845,29 +1871,10 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
} break;
case Animation::TYPE_VALUE: {
Variant v = animation->track_get_key_value(track, key_idx);
//text+="value: "+String(v)+"\n";
bool prop_exists = false;
Variant::Type valid_type = Variant::NIL;
Object *obj = NULL;
RES res;
Vector<StringName> leftover_path;
Node *node = root->get_node_and_resource(animation->track_get_path(track), res, leftover_path);
if (res.is_valid()) {
obj = res.ptr();
} else if (node) {
obj = node;
}
if (obj) {
valid_type = obj->get_static_property_type_indexed(leftover_path, &prop_exists);
}
const Variant &v = animation->track_get_key_value(track, key_idx);
text += "Type: " + Variant::get_type_name(v.get_type()) + "\n";
if (prop_exists && !Variant::can_convert(v.get_type(), valid_type)) {
Variant::Type valid_type = Variant::NIL;
if (!_is_value_key_valid(v, valid_type)) {
text += "Value: " + String(v) + " (Invalid, expected type: " + Variant::get_type_name(valid_type) + ")\n";
} else {
text += "Value: " + String(v) + "\n";
@ -4122,6 +4129,7 @@ void AnimationTrackEditor::_update_key_edit() {
key_edit = memnew(AnimationTrackKeyEdit);
key_edit->animation = animation;
key_edit->track = selection.front()->key().track;
key_edit->use_fps = timeline->is_using_fps();
float ofs = animation->track_get_key_time(key_edit->track, selection.front()->key().key);
key_edit->key_ofs = ofs;

View File

@ -31,6 +31,11 @@
#ifndef ANIMATION_TRACK_EDITOR_H
#define ANIMATION_TRACK_EDITOR_H
#include "editor/editor_data.h"
#include "editor/editor_spin_slider.h"
#include "editor/property_editor.h"
#include "editor/property_selector.h"
#include "scene/animation/animation_cache.h"
#include "scene/gui/control.h"
#include "scene/gui/file_dialog.h"
#include "scene/gui/menu_button.h"
@ -40,12 +45,6 @@
#include "scene/gui/tab_container.h"
#include "scene/gui/texture_rect.h"
#include "scene/gui/tool_button.h"
#include "editor/property_selector.h"
#include "editor_data.h"
#include "editor_spin_slider.h"
#include "property_editor.h"
#include "scene/animation/animation_cache.h"
#include "scene/resources/animation.h"
#include "scene_tree_editor.h"
@ -175,8 +174,9 @@ class AnimationTrackEdit : public Control {
void _path_entered(const String &p_text);
void _play_position_draw();
mutable int dropping_at;
bool _is_value_key_valid(const Variant &p_key_value, Variant::Type &r_valid_type) const;
mutable int dropping_at;
float insert_at_pos;
bool moving_selection_attempt;
int select_single_attempt;

View File

@ -772,7 +772,7 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
}
}
if (!info.is_singleton && !info.in_editor) {
if (!info.is_singleton && !info.in_editor && info.node != NULL) {
memdelete(info.node);
info.node = NULL;
}

View File

@ -560,6 +560,7 @@ void EditorData::move_edited_scene_index(int p_idx, int p_to_idx) {
ERR_FAIL_INDEX(p_to_idx, edited_scene.size());
SWAP(edited_scene.write[p_idx], edited_scene.write[p_to_idx]);
}
void EditorData::remove_scene(int p_idx) {
ERR_FAIL_INDEX(p_idx, edited_scene.size());
if (edited_scene[p_idx].root) {

View File

@ -611,6 +611,7 @@ void EditorExportPlugin::_bind_methods() {
BIND_VMETHOD(MethodInfo("_export_file", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "type"), PropertyInfo(Variant::POOL_STRING_ARRAY, "features")));
BIND_VMETHOD(MethodInfo("_export_begin", PropertyInfo(Variant::POOL_STRING_ARRAY, "features"), PropertyInfo(Variant::BOOL, "is_debug"), PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags")));
BIND_VMETHOD(MethodInfo("_export_end"));
}
EditorExportPlugin::EditorExportPlugin() {

View File

@ -175,8 +175,9 @@ String EditorHelp::_fix_constant(const String &p_constant) const {
if (p_constant.strip_edges() == "2147483647") {
return "0x7FFFFFFF";
}
if (p_constant.strip_edges() == "1048575") {
return "0xfffff";
return "0xFFFFF";
}
return p_constant;

View File

@ -504,6 +504,7 @@ void EditorNode::_fs_changed() {
void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
List<String> scenes; //will load later
int current_tab = scene_tabs->get_current_tab();
for (int i = 0; i < p_resources.size(); i++) {
String file_type = ResourceLoader::get_resource_type(p_resources[i]);
@ -526,6 +527,8 @@ void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
for (List<String>::Element *E = scenes.front(); E; E = E->next()) {
reload_scene(E->get());
}
scene_tabs->set_current_tab(current_tab);
}
void EditorNode::_sources_changed(bool p_exist) {
@ -1189,6 +1192,17 @@ void EditorNode::save_all_scenes() {
_save_all_scenes();
}
void EditorNode::save_scene_list(Vector<String> p_scene_filenames) {
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
Node *scene = editor_data.get_edited_scene_root(i);
if (scene && (p_scene_filenames.find(scene->get_filename()) >= 0)) {
_save_scene(scene->get_filename(), i);
}
}
}
void EditorNode::restart_editor() {
exiting = true;
@ -2744,7 +2758,7 @@ bool EditorNode::is_addon_plugin_enabled(const String &p_addon) const {
return plugin_addons.has(p_addon);
}
void EditorNode::_remove_edited_scene() {
void EditorNode::_remove_edited_scene(bool p_change_tab) {
int new_index = editor_data.get_edited_scene();
int old_index = new_index;
@ -2760,18 +2774,19 @@ void EditorNode::_remove_edited_scene() {
if (editor_data.get_scene_path(old_index) != String()) {
ScriptEditor::get_singleton()->close_builtin_scripts_from_scene(editor_data.get_scene_path(old_index));
}
_scene_tab_changed(new_index);
if (p_change_tab) _scene_tab_changed(new_index);
editor_data.remove_scene(old_index);
editor_data.get_undo_redo().clear_history(false);
_update_title();
_update_scene_tabs();
}
void EditorNode::_remove_scene(int index) {
void EditorNode::_remove_scene(int index, bool p_change_tab) {
if (editor_data.get_edited_scene() == index) {
//Scene to remove is current scene
_remove_edited_scene();
_remove_edited_scene(p_change_tab);
} else {
//Scene to remove is not active scene
editor_data.remove_scene(index);
@ -4023,6 +4038,14 @@ bool EditorNode::has_scenes_in_session() {
return !scenes.empty();
}
int EditorNode::get_current_tab() {
return scene_tabs->get_current_tab();
}
void EditorNode::set_current_tab(int p_tab) {
scene_tabs->set_current_tab(p_tab);
}
void EditorNode::_update_layouts_menu() {
editor_layouts->clear();
@ -4612,8 +4635,7 @@ void EditorNode::reload_scene(const String &p_path) {
if (scene_idx == -1) {
if (get_edited_scene()) {
//scene is not open, so at it might be instanced, just refresh, set tab to itself and it will reload
set_current_scene(current_tab);
//scene is not open, so at it might be instanced. We'll refresh the whole scene later.
editor_data.get_undo_redo().clear_history();
}
return;
@ -4623,17 +4645,19 @@ void EditorNode::reload_scene(const String &p_path) {
editor_data.apply_changes_in_editors();
_set_scene_metadata(p_path);
}
//remove scene
_remove_scene(scene_idx);
//reload scene
//remove scene
_remove_scene(scene_idx, false);
//reload scene
load_scene(p_path, true, false, true, true);
//adjust index so tab is back a the previous position
editor_data.move_edited_scene_to_index(scene_idx);
get_undo_redo()->clear_history();
//recover the tab
scene_tabs->set_current_tab(current_tab);
_scene_tab_changed(current_tab);
}
int EditorNode::plugin_init_callback_count = 0;
@ -5440,7 +5464,7 @@ EditorNode::EditorNode() {
p->add_shortcut(ED_SHORTCUT("editor/undo", TTR("Undo"), KEY_MASK_CMD + KEY_Z), EDIT_UNDO, true);
p->add_shortcut(ED_SHORTCUT("editor/redo", TTR("Redo"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Z), EDIT_REDO, true);
p->add_separator();
p->add_item(TTR("Revert Scene"), EDIT_REVERT);
p->add_shortcut(ED_SHORTCUT("editor/revert_scene", TTR("Revert Scene")), EDIT_REVERT);
recent_scenes = memnew(PopupMenu);
recent_scenes->set_name("RecentScenes");
@ -5460,10 +5484,10 @@ EditorNode::EditorNode() {
p = project_menu->get_popup();
p->set_hide_on_window_lose_focus(true);
p->add_item(TTR("Project Settings"), RUN_SETTINGS);
p->add_shortcut(ED_SHORTCUT("editor/project_settings", TTR("Project Settings")), RUN_SETTINGS);
p->add_separator();
p->connect("id_pressed", this, "_menu_option");
p->add_item(TTR("Export"), FILE_EXPORT_PROJECT);
p->add_shortcut(ED_SHORTCUT("editor/export", TTR("Export")), FILE_EXPORT_PROJECT);
plugin_config_dialog = memnew(PluginConfigDialog);
plugin_config_dialog->connect("plugin_ready", this, "_on_plugin_ready");
@ -5474,10 +5498,10 @@ EditorNode::EditorNode() {
tool_menu->connect("index_pressed", this, "_tool_menu_option");
p->add_child(tool_menu);
p->add_submenu_item(TTR("Tools"), "Tools");
tool_menu->add_item(TTR("Orphan Resource Explorer"), TOOLS_ORPHAN_RESOURCES);
tool_menu->add_shortcut(ED_SHORTCUT("editor/orphan_resource_explorer", TTR("Orphan Resource Explorer")), TOOLS_ORPHAN_RESOURCES);
p->add_separator();
p->add_item(TTR("Open Project Data Folder"), RUN_PROJECT_DATA_FOLDER);
p->add_shortcut(ED_SHORTCUT("editor/open_project_data_folder", TTR("Open Project Data Folder")), RUN_PROJECT_DATA_FOLDER);
p->add_separator();
#ifdef OSX_ENABLED
@ -5501,21 +5525,21 @@ EditorNode::EditorNode() {
p = debug_menu->get_popup();
p->set_hide_on_window_lose_focus(true);
p->set_hide_on_item_selection(false);
p->add_check_item(TTR("Deploy with Remote Debug"), RUN_DEPLOY_REMOTE_DEBUG);
p->add_check_shortcut(ED_SHORTCUT("editor/deploy_with_remote_debug", TTR("Deploy with Remote Debug")), RUN_DEPLOY_REMOTE_DEBUG);
p->set_item_tooltip(p->get_item_count() - 1, TTR("When exporting or deploying, the resulting executable will attempt to connect to the IP of this computer in order to be debugged."));
p->add_check_item(TTR("Small Deploy with Network FS"), RUN_FILE_SERVER);
p->add_check_shortcut(ED_SHORTCUT("editor/small_deploy_with_network_fs", TTR("Small Deploy with Network FS")), RUN_FILE_SERVER);
p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is enabled, export or deploy will produce a minimal executable.\nThe filesystem will be provided from the project by the editor over the network.\nOn Android, deploy will use the USB cable for faster performance. This option speeds up testing for games with a large footprint."));
p->add_separator();
p->add_check_item(TTR("Visible Collision Shapes"), RUN_DEBUG_COLLISONS);
p->add_check_shortcut(ED_SHORTCUT("editor/visible_collision_shapes", TTR("Visible Collision Shapes")), RUN_DEBUG_COLLISONS);
p->set_item_tooltip(p->get_item_count() - 1, TTR("Collision shapes and raycast nodes (for 2D and 3D) will be visible on the running game if this option is turned on."));
p->add_check_item(TTR("Visible Navigation"), RUN_DEBUG_NAVIGATION);
p->add_check_shortcut(ED_SHORTCUT("editor/visible_navigation", TTR("Visible Navigation")), RUN_DEBUG_NAVIGATION);
p->set_item_tooltip(p->get_item_count() - 1, TTR("Navigation meshes and polygons will be visible on the running game if this option is turned on."));
p->add_separator();
//those are now on by default, since they are harmless
p->add_check_item(TTR("Sync Scene Changes"), RUN_LIVE_DEBUG);
p->add_check_shortcut(ED_SHORTCUT("editor/sync_scene_changes", TTR("Sync Scene Changes")), RUN_LIVE_DEBUG);
p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is turned on, any changes made to the scene in the editor will be replicated in the running game.\nWhen used remotely on a device, this is more efficient with network filesystem."));
p->set_item_checked(p->get_item_count() - 1, true);
p->add_check_item(TTR("Sync Script Changes"), RUN_RELOAD_SCRIPTS);
p->add_check_shortcut(ED_SHORTCUT("editor/sync_script_changes", TTR("Sync Script Changes")), RUN_RELOAD_SCRIPTS);
p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is turned on, any script that is saved will be reloaded on the running game.\nWhen used remotely on a device, this is more efficient with network filesystem."));
p->set_item_checked(p->get_item_count() - 1, true);
p->connect("id_pressed", this, "_menu_option");
@ -5531,7 +5555,7 @@ EditorNode::EditorNode() {
p = settings_menu->get_popup();
p->set_hide_on_window_lose_focus(true);
p->add_item(TTR("Editor Settings"), SETTINGS_PREFERENCES);
p->add_shortcut(ED_SHORTCUT("editor/editor_settings", TTR("Editor Settings")), SETTINGS_PREFERENCES);
p->add_separator();
editor_layouts = memnew(PopupMenu);
@ -5571,12 +5595,12 @@ EditorNode::EditorNode() {
p->connect("id_pressed", this, "_menu_option");
p->add_icon_shortcut(gui_base->get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search"), KEY_F4), HELP_SEARCH);
p->add_separator();
p->add_icon_item(gui_base->get_icon("Instance", "EditorIcons"), TTR("Online Docs"), HELP_DOCS);
p->add_icon_item(gui_base->get_icon("Instance", "EditorIcons"), TTR("Q&A"), HELP_QA);
p->add_icon_item(gui_base->get_icon("Instance", "EditorIcons"), TTR("Issue Tracker"), HELP_ISSUES);
p->add_icon_item(gui_base->get_icon("Instance", "EditorIcons"), TTR("Community"), HELP_COMMUNITY);
p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/online_docs", TTR("Online Docs")), HELP_DOCS);
p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/q&a", TTR("Q&A")), HELP_QA);
p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/issue_tracker", TTR("Issue Tracker")), HELP_ISSUES);
p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/community", TTR("Community")), HELP_COMMUNITY);
p->add_separator();
p->add_icon_item(gui_base->get_icon("Godot", "EditorIcons"), TTR("About"), HELP_ABOUT);
p->add_icon_shortcut(gui_base->get_icon("Godot", "EditorIcons"), ED_SHORTCUT("editor/about", TTR("About")), HELP_ABOUT);
HBoxContainer *play_hb = memnew(HBoxContainer);
menu_hb->add_child(play_hb);

View File

@ -499,8 +499,8 @@ private:
static void _editor_file_dialog_unregister(EditorFileDialog *p_dialog);
void _cleanup_scene();
void _remove_edited_scene();
void _remove_scene(int index);
void _remove_edited_scene(bool p_change_tab = true);
void _remove_scene(int index, bool p_change_tab = true);
bool _find_and_save_resource(RES p_res, Map<RES, bool> &processed, int32_t flags);
bool _find_and_save_edited_subresources(Object *obj, Map<RES, bool> &processed, int32_t flags);
void _save_edited_subresources(Node *scene, Map<RES, bool> &processed, int32_t flags);
@ -615,6 +615,12 @@ protected:
void _notification(int p_what);
static void _bind_methods();
protected:
friend class FileSystemDock;
int get_current_tab();
void set_current_tab(int p_tab);
public:
bool call_build();
@ -786,6 +792,7 @@ public:
void remove_tool_menu_item(const String &p_name);
void save_all_scenes();
void save_scene_list(Vector<String> p_scene_filenames);
void restart_editor();
void dim_editor(bool p_dimming);

View File

@ -2289,6 +2289,16 @@ void EditorPropertyResource::_update_menu_items() {
E = E->next();
}
List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes);
E = global_classes.front();
while (E) {
if (EditorNode::get_editor_data().script_class_is_parent(E->get(), base_type)) {
valid_inheritors.insert(E->get());
}
E = E->next();
}
for (Set<String>::Element *F = valid_inheritors.front(); F; F = F->next()) {
String t = F->get();
@ -2305,7 +2315,7 @@ void EditorPropertyResource::_update_menu_items() {
}
}
if (!is_custom_resource && !ClassDB::can_instance(t))
if (!is_custom_resource && !(ScriptServer::is_global_class(t) || ClassDB::can_instance(t)))
continue;
inheritors_array.push_back(t);

View File

@ -268,6 +268,11 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
String host_lang = OS::get_singleton()->get_locale();
host_lang = TranslationServer::standardize_locale(host_lang);
// Some locales are not properly supported currently in Godot due to lack of font shaping
// (e.g. Arabic or Hindi), so even though we have work in progress translations for them,
// we skip them as they don't render properly. (GH-28577)
const Vector<String> locales_to_skip = String("ar,bn,fa,he,hi,ml,si,ta,te,ur").split(",");
String best;
EditorTranslationList *etl = _editor_translations;
@ -275,6 +280,15 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
while (etl->data) {
const String &locale = etl->lang;
// Skip locales which we can't render properly (see above comment).
// Test against language code without regional variants (e.g. ur_PK).
String lang_code = locale.get_slice("_", 0);
if (locales_to_skip.find(lang_code) != -1) {
etl++;
continue;
}
lang_hint += ",";
lang_hint += locale;
@ -543,6 +557,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/2d/bone_outline_size", 2);
_initial_set("editors/2d/keep_margins_when_changing_anchors", false);
_initial_set("editors/2d/viewport_border_color", Color(0.4, 0.4, 1.0, 0.4));
_initial_set("editors/2d/constrain_editor_view", true);
_initial_set("editors/2d/warped_mouse_panning", true);
_initial_set("editors/2d/simple_spacebar_panning", false);
_initial_set("editors/2d/scroll_to_pan", false);

View File

@ -1167,6 +1167,21 @@ void FileSystemDock::_update_favorites_list_after_move(const Map<String, String>
EditorSettings::get_singleton()->set_favorites(new_favorites);
}
void FileSystemDock::_save_scenes_after_move(const Map<String, String> &p_renames) const {
Vector<String> remaps;
_find_remaps(EditorFileSystem::get_singleton()->get_filesystem(), p_renames, remaps);
Vector<String> new_filenames;
for (int i = 0; i < remaps.size(); ++i) {
String file = p_renames.has(remaps[i]) ? p_renames[remaps[i]] : remaps[i];
if (ResourceLoader::get_resource_type(file) == "PackedScene") {
new_filenames.push_back(file);
}
}
editor->save_scene_list(new_filenames);
}
void FileSystemDock::_make_dir_confirm() {
String dir_name = make_dir_dialog_text->get_text().strip_edges();
@ -1241,14 +1256,21 @@ void FileSystemDock::_rename_operation_confirm() {
Map<String, String> file_renames;
Map<String, String> folder_renames;
_try_move_item(to_rename, new_path, file_renames, folder_renames);
int current_tab = editor->get_current_tab();
_update_dependencies_after_move(file_renames);
_update_resource_paths_after_move(file_renames);
_update_project_settings_after_move(file_renames);
_update_favorites_list_after_move(file_renames, folder_renames);
//Rescan everything
editor->set_current_tab(current_tab);
print_verbose("FileSystem: calling rescan.");
_rescan();
print_verbose("FileSystem: saving moved scenes.");
_save_scenes_after_move(file_renames);
}
void FileSystemDock::_duplicate_operation_confirm() {
@ -1334,13 +1356,20 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool overw
}
if (is_moved) {
int current_tab = editor->get_current_tab();
_update_dependencies_after_move(file_renames);
_update_resource_paths_after_move(file_renames);
_update_project_settings_after_move(file_renames);
_update_favorites_list_after_move(file_renames, folder_renames);
editor->set_current_tab(current_tab);
print_verbose("FileSystem: calling rescan.");
_rescan();
print_verbose("FileSystem: saving moved scenes.");
_save_scenes_after_move(file_renames);
}
}

View File

@ -201,6 +201,7 @@ private:
void _try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const;
void _update_dependencies_after_move(const Map<String, String> &p_renames) const;
void _update_resource_paths_after_move(const Map<String, String> &p_renames) const;
void _save_scenes_after_move(const Map<String, String> &p_renames) const;
void _update_favorites_list_after_move(const Map<String, String> &p_files_renames, const Map<String, String> &p_folders_renames) const;
void _update_project_settings_after_move(const Map<String, String> &p_folders_renames) const;

View File

@ -751,7 +751,6 @@ void FindInFilesPanel::_on_replace_text_changed(String text) {
void FindInFilesPanel::_on_replace_all_clicked() {
String replace_text = get_replace_text();
ERR_FAIL_COND(replace_text.empty());
PoolStringArray modified_files;
@ -887,7 +886,7 @@ String FindInFilesPanel::get_replace_text() {
void FindInFilesPanel::update_replace_buttons() {
String text = get_replace_text();
bool disabled = text.empty() || _finder->is_searching();
bool disabled = _finder->is_searching();
_replace_all_button->set_disabled(disabled);
}

View File

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="128"
height="128"
version="1.1"
viewBox="0 0 128 128"
id="svg6"
sodipodi:docname="icon_gizmo_c_p_u_particles.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1606"
inkscape:window-height="821"
id="namedview8"
showgrid="false"
inkscape:zoom="2.6074563"
inkscape:cx="101.29539"
inkscape:cy="83.191634"
inkscape:window-x="295"
inkscape:window-y="81"
inkscape:window-maximized="0"
inkscape:current-layer="svg6"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<path
style="display:inline;opacity:1;fill:#f7f5cf;fill-opacity:1;stroke:#b4b4b4;stroke-width:2.56380486;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 35.503779,1.2819066 c -3.570424,0 -6.435164,2.9483368 -6.435164,6.6019028 v 4.3900146 c 0,0.889114 0.169457,1.726301 0.478513,2.49893 H 19.465369 c -3.570424,0 -6.435167,2.931453 -6.435167,6.585021 v 7.969562 c -0.341543,-0.0568 -0.648813,-0.202614 -1.006525,-0.202614 H 7.7335674 c -3.5704232,0 -6.451665,2.948338 -6.451665,6.601904 v 3.224972 c 0,3.653568 2.8812418,6.585016 6.451665,6.585016 h 4.2901096 c 0.358169,0 0.664563,-0.14568 1.006525,-0.202618 V 83.83104 C 12.688659,83.77398 12.381388,83.628424 12.023677,83.628424 H 7.7335674 c -3.5704232,0 -6.451665,2.948332 -6.451665,6.601908 v 3.224971 c 0,3.653575 2.8812418,6.585017 6.451665,6.585017 h 4.2901096 c 0.358169,0 0.664563,-0.145692 1.006525,-0.202612 v 9.725542 c 0,3.6536 2.864743,6.60193 6.435167,6.60193 h 9.603246 v 3.951 c 0,3.65357 2.86474,6.60192 6.435164,6.60192 h 3.15158 c 3.57042,0 6.451663,-2.94836 6.451663,-6.60192 v -3.95104 h 37.224955 v 3.951 c 0,3.65358 2.86474,6.60193 6.435166,6.60193 h 3.151583 c 3.570418,0 6.451653,-2.94836 6.451653,-6.60193 v -3.951 h 10.725281 c 3.57043,0 6.45166,-2.94833 6.45166,-6.60191 v -9.607372 c 0.14985,0.0105 0.27643,0.0846 0.42899,0.0846 h 4.29014 c 3.5704,0 6.45165,-2.931432 6.45165,-6.585011 v -3.224992 c 0,-3.653565 -2.88125,-6.601906 -6.45165,-6.601906 h -4.29014 c -0.15231,0 -0.27938,0.07348 -0.42899,0.08472 V 45.452198 c 0.14985,0.01042 0.27643,0.08445 0.42899,0.08445 h 4.29014 c 3.5704,0 6.45165,-2.931451 6.45165,-6.585023 v -3.224986 c 0,-3.653566 -2.88125,-6.601906 -6.45165,-6.601906 h -4.29014 c -0.15231,0 -0.27938,0.07392 -0.42899,0.08446 v -7.851429 c 0,-3.653567 -2.88123,-6.585019 -6.45166,-6.585021 H 97.875379 c 0.309043,-0.772641 0.494982,-1.609791 0.494982,-2.498929 V 7.8838054 c 0,-3.6535651 -2.881246,-6.601903 -6.451662,-6.601903 h -3.15158 c -3.570428,0 -6.435167,2.9483379 -6.435167,6.601903 V 12.27382 c 0,0.889115 0.16948,1.726301 0.478507,2.49893 H 44.612011 c 0.309083,-0.772642 0.495011,-1.609792 0.495011,-2.49893 V 7.8838054 c 0,-3.6535651 -2.881243,-6.601903 -6.451663,-6.601903 z"
id="path4542"
inkscape:connector-curvature="0" />
<path
style="opacity:1;fill:#b4b4b4;fill-opacity:1;stroke-width:8.54601765"
d="M 62.861474,21.661698 A 27.707285,31.502779 0 0 1 90.004671,47.07312 18.471523,18.901669 0 0 1 105.96058,65.764449 18.471523,18.901669 0 0 1 87.480108,84.658396 H 38.226348 A 18.471523,18.901669 0 0 1 19.762375,65.764449 18.471523,18.901669 0 0 1 35.685283,47.056234 27.707285,31.502779 0 0 1 62.861474,21.661698 Z"
id="path4540"
inkscape:connector-curvature="0" />
<path
style="opacity:1;fill:#b4b4b4;fill-opacity:1;stroke-width:8.54601765"
d="m 38.226348,90.956369 a 6.1571744,6.3005562 0 0 1 6.154657,6.297979 6.1571744,6.3005562 0 0 1 -6.154657,6.314882 6.1571744,6.3005562 0 0 1 -6.154657,-6.314882 6.1571744,6.3005562 0 0 1 6.154657,-6.297979 z"
id="path4538"
inkscape:connector-curvature="0" />
<path
style="opacity:1;fill:#b4b4b4;fill-opacity:1;stroke-width:8.54601765"
d="m 87.480108,90.956369 a 6.1571744,6.3005562 0 0 1 6.171159,6.297979 6.1571744,6.3005562 0 0 1 -6.171159,6.314882 6.1571744,6.3005562 0 0 1 -6.154656,-6.314882 6.1571744,6.3005562 0 0 1 6.154656,-6.297979 z"
id="path4536"
inkscape:connector-curvature="0" />
<path
style="opacity:1;fill:#b4b4b4;fill-opacity:1;stroke-width:8.54601765"
d="m 62.861474,97.254348 a 6.1571744,6.3005562 0 0 1 6.154662,6.314882 6.1571744,6.3005562 0 0 1 -6.154662,6.29797 6.1571744,6.3005562 0 0 1 -6.154651,-6.29797 6.1571744,6.3005562 0 0 1 6.154651,-6.314882 z"
id="rect822"
inkscape:connector-curvature="0" />
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Layer 1"
transform="translate(-0.35794507,-5.5049216)" />
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -1,5 +0,0 @@
<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1044.4)">
<rect transform="rotate(-45)" x="-741.53" y="741.08" width="6.1027" height="6.1027" ry=".76286" fill="#fff"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 253 B

View File

@ -2087,22 +2087,23 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye
animation->add_track(Animation::TYPE_VALUE);
animation->track_set_path(track_idx, node_path);
if (track.weight_tracks[i].interpolation <= GLTFAnimation::INTERP_STEP) {
animation->track_set_interpolation_type(track_idx, track.weight_tracks[i].interpolation == GLTFAnimation::INTERP_STEP ? Animation::INTERPOLATION_NEAREST : Animation::INTERPOLATION_NEAREST);
// Only LINEAR and STEP (NEAREST) can be supported out of the box by Godot's Animation,
// the other modes have to be baked.
GLTFAnimation::Interpolation gltf_interp = track.weight_tracks[i].interpolation;
if (gltf_interp == GLTFAnimation::INTERP_LINEAR || gltf_interp == GLTFAnimation::INTERP_STEP) {
animation->track_set_interpolation_type(track_idx, gltf_interp == GLTFAnimation::INTERP_STEP ? Animation::INTERPOLATION_NEAREST : Animation::INTERPOLATION_LINEAR);
for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
float t = track.weight_tracks[i].times[j];
float w = track.weight_tracks[i].values[j];
animation->track_insert_key(track_idx, t, w);
}
} else {
//must bake, apologies.
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
float increment = 1.0 / float(bake_fps);
float time = 0.0;
bool last = false;
while (true) {
_interpolate_track<float>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, track.weight_tracks[i].interpolation);
_interpolate_track<float>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp);
if (last) {
break;
}

View File

@ -1094,7 +1094,7 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15));
r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "animation/filter_script", PROPERTY_HINT_MULTILINE_TEXT), ""));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/storage", PROPERTY_HINT_ENUM, "Built-In,Files"), animations_out ? true : false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/storage", PROPERTY_HINT_ENUM, "Built-In,Files", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), animations_out ? true : false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/keep_custom_tracks"), animations_out ? true : false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/optimizer/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "animation/optimizer/max_linear_error"), 0.05));

View File

@ -1430,6 +1430,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() {
new_state["show_rulers"] = false;
new_state["show_guides"] = false;
new_state["show_helpers"] = false;
new_state["show_zoom_control"] = false;
// TODO: Save/restore only affected entries
CanvasItemEditor::get_singleton()->set_state(new_state);
}
@ -1482,7 +1483,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() {
if (valid) {
player->seek(pos, true);
get_tree()->flush_transform_notifications(); // Needed for transforms of Spatials
values_backup.update_skeletons(); // Needed for Skeletons
values_backup.update_skeletons(); // Needed for Skeletons (2D & 3D)
VS::get_singleton()->viewport_set_active(onion.captures[cidx], true);
VS::get_singleton()->viewport_set_parent_viewport(root_vp, onion.captures[cidx]);

View File

@ -726,6 +726,7 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByt
image_data = cached_data;
file->close();
memdelete(file);
}
}
@ -800,6 +801,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
if (file) {
file->store_line(new_etag);
file->close();
memdelete(file);
}
int len = p_data.size();
@ -809,6 +811,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
file->store_32(len);
file->store_buffer(r.ptr(), len);
file->close();
memdelete(file);
}
break;
@ -848,6 +851,7 @@ void EditorAssetLibrary::_update_image_queue() {
if (file) {
headers.push_back("If-None-Match: " + file->get_line());
file->close();
memdelete(file);
}
}

View File

@ -3547,18 +3547,19 @@ void CanvasItemEditor::_update_scrollbars() {
// Constraints the view offset and updates the scrollbars
Point2 begin = canvas_item_rect.position;
Point2 end = canvas_item_rect.position + canvas_item_rect.size - local_rect.size / zoom;
bool constrain_editor_view = bool(EditorSettings::get_singleton()->get("editors/2d/constrain_editor_view"));
if (canvas_item_rect.size.height <= (local_rect.size.y / zoom)) {
if (ABS(begin.y - previous_update_view_offset.y) < ABS(begin.y - view_offset.y)) {
if (constrain_editor_view && ABS(begin.y - previous_update_view_offset.y) < ABS(begin.y - view_offset.y)) {
view_offset.y = previous_update_view_offset.y;
}
v_scroll->hide();
} else {
if (view_offset.y > end.y && view_offset.y > previous_update_view_offset.y) {
if (constrain_editor_view && view_offset.y > end.y && view_offset.y > previous_update_view_offset.y) {
view_offset.y = MAX(end.y, previous_update_view_offset.y);
}
if (view_offset.y < begin.y && view_offset.y < previous_update_view_offset.y) {
if (constrain_editor_view && view_offset.y < begin.y && view_offset.y < previous_update_view_offset.y) {
view_offset.y = MIN(begin.y, previous_update_view_offset.y);
}
@ -3569,16 +3570,16 @@ void CanvasItemEditor::_update_scrollbars() {
}
if (canvas_item_rect.size.width <= (local_rect.size.x / zoom)) {
if (ABS(begin.x - previous_update_view_offset.x) < ABS(begin.x - view_offset.x)) {
if (constrain_editor_view && ABS(begin.x - previous_update_view_offset.x) < ABS(begin.x - view_offset.x)) {
view_offset.x = previous_update_view_offset.x;
}
h_scroll->hide();
} else {
if (view_offset.x > end.x && view_offset.x > previous_update_view_offset.x) {
if (constrain_editor_view && view_offset.x > end.x && view_offset.x > previous_update_view_offset.x) {
view_offset.x = MAX(end.x, previous_update_view_offset.x);
}
if (view_offset.x < begin.x && view_offset.x < previous_update_view_offset.x) {
if (constrain_editor_view && view_offset.x < begin.x && view_offset.x < previous_update_view_offset.x) {
view_offset.x = MIN(begin.x, previous_update_view_offset.x);
}
@ -3903,6 +3904,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
show_rulers = !show_rulers;
int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
view_menu->get_popup()->set_item_checked(idx, show_rulers);
_update_scrollbars();
viewport->update();
} break;
case SHOW_GUIDES: {
@ -4371,6 +4373,7 @@ Dictionary CanvasItemEditor::get_state() const {
state["show_rulers"] = show_rulers;
state["show_guides"] = show_guides;
state["show_helpers"] = show_helpers;
state["show_zoom_control"] = zoom_hb->is_visible();
state["show_edit_locks"] = show_edit_locks;
state["snap_rotation"] = snap_rotation;
state["snap_relative"] = snap_relative;
@ -4381,6 +4384,7 @@ Dictionary CanvasItemEditor::get_state() const {
void CanvasItemEditor::set_state(const Dictionary &p_state) {
bool update_scrollbars = false;
Dictionary state = p_state;
if (state.has("zoom")) {
zoom = p_state["zoom"];
@ -4389,7 +4393,7 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
if (state.has("ofs")) {
view_offset = p_state["ofs"];
previous_update_view_offset = view_offset;
_update_scrollbars();
update_scrollbars = true;
}
if (state.has("grid_offset")) {
@ -4477,6 +4481,7 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
show_rulers = state["show_rulers"];
int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
view_menu->get_popup()->set_item_checked(idx, show_rulers);
update_scrollbars = true;
}
if (state.has("show_guides")) {
@ -4497,6 +4502,11 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
view_menu->get_popup()->set_item_checked(idx, show_edit_locks);
}
if (state.has("show_zoom_control")) {
// This one is not user-controllable, but instrumentable
zoom_hb->set_visible(state["show_zoom_control"]);
}
if (state.has("snap_rotation")) {
snap_rotation = state["snap_rotation"];
int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
@ -4521,6 +4531,9 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones);
}
if (update_scrollbars) {
_update_scrollbars();
}
viewport->update();
}

View File

@ -1906,10 +1906,11 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
String flags = EditorSettings::get_singleton()->get("text_editor/external/exec_flags");
List<String> args;
bool has_file_flag = false;
String script_path = ProjectSettings::get_singleton()->globalize_path(p_resource->get_path());
if (flags.size()) {
String project_path = ProjectSettings::get_singleton()->get_resource_path();
String script_path = ProjectSettings::get_singleton()->globalize_path(p_resource->get_path());
flags = flags.replacen("{line}", itos(p_line > 0 ? p_line : 0));
flags = flags.replacen("{col}", itos(p_col));
@ -1931,6 +1932,9 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
} else if (flags[i] == '\0' || (!inside_quotes && flags[i] == ' ')) {
String arg = flags.substr(from, num_chars);
if (arg.find("{file}") != -1) {
has_file_flag = true;
}
// do path replacement here, else there will be issues with spaces and quotes
arg = arg.replacen("{project}", project_path);
@ -1945,6 +1949,11 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
}
}
// Default to passing script path if no {file} flag is specified.
if (!has_file_flag) {
args.push_back(script_path);
}
Error err = OS::get_singleton()->execute(path, args, false);
if (err == OK)
return false;
@ -3331,7 +3340,8 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/open_scripts/list_script_names_as", PROPERTY_HINT_ENUM, "Name,Parent Directory And Name,Full Path"));
EDITOR_DEF("text_editor/open_scripts/list_script_names_as", 0);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "text_editor/external/exec_path", PROPERTY_HINT_GLOBAL_FILE));
EDITOR_DEF("text_editor/external/exec_flags", "");
EDITOR_DEF("text_editor/external/exec_flags", "{file}");
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "text_editor/external/exec_flags", PROPERTY_HINT_PLACEHOLDER_TEXT, "Call flags with placeholders: {project}, {file}, {col}, {line}."));
ED_SHORTCUT("script_editor/open_recent", TTR("Open Recent"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_T);
ED_SHORTCUT("script_editor/clear_recent", TTR("Clear Recent Files"));

View File

@ -165,7 +165,7 @@ void ScriptTextEditor::_load_theme_settings() {
text_edit->add_color_override("safe_line_number_color", safe_line_number_color);
text_edit->add_color_override("caret_color", caret_color);
text_edit->add_color_override("caret_background_color", caret_background_color);
text_edit->add_color_override("font_selected_color", text_selected_color);
text_edit->add_color_override("font_color_selected", text_selected_color);
text_edit->add_color_override("selection_color", selection_color);
text_edit->add_color_override("brace_mismatch_color", brace_mismatch_color);
text_edit->add_color_override("current_line_color", current_line_color);
@ -1329,7 +1329,9 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
if (has_color) {
String line = tx->get_line(row);
color_line = row;
color_position.x = row;
color_position.y = col;
int begin = 0;
int end = 0;
bool valid = false;
@ -1369,10 +1371,15 @@ void ScriptTextEditor::_color_changed(const Color &p_color) {
new_args = String("(" + rtos(p_color.r) + ", " + rtos(p_color.g) + ", " + rtos(p_color.b) + ", " + rtos(p_color.a) + ")");
}
String line = code_editor->get_text_edit()->get_line(color_line);
String new_line = line.replace(color_args, new_args);
String line = code_editor->get_text_edit()->get_line(color_position.x);
int color_args_pos = line.find(color_args, color_position.y);
String line_with_replaced_args = line;
line_with_replaced_args.erase(color_args_pos, color_args.length());
line_with_replaced_args = line_with_replaced_args.insert(color_args_pos, new_args);
color_args = new_args;
code_editor->get_text_edit()->set_line(color_line, new_line);
code_editor->get_text_edit()->set_line(color_position.x, line_with_replaced_args);
code_editor->get_text_edit()->update();
}
void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition) {
@ -1465,6 +1472,7 @@ ScriptTextEditor::ScriptTextEditor() {
color_panel = memnew(PopupPanel);
add_child(color_panel);
color_picker = memnew(ColorPicker);
color_picker->set_deferred_mode(true);
color_panel->add_child(color_picker);
color_picker->connect("color_changed", this, "_color_changed");

View File

@ -59,7 +59,7 @@ class ScriptTextEditor : public ScriptEditorBase {
PopupPanel *color_panel;
ColorPicker *color_picker;
int color_line;
Vector2 color_position;
String color_args;
void _update_member_keywords();

View File

@ -102,7 +102,7 @@ void ShaderTextEditor::_load_theme_settings() {
get_text_edit()->add_color_override("line_number_color", line_number_color);
get_text_edit()->add_color_override("caret_color", caret_color);
get_text_edit()->add_color_override("caret_background_color", caret_background_color);
get_text_edit()->add_color_override("font_selected_color", text_selected_color);
get_text_edit()->add_color_override("font_color_selected", text_selected_color);
get_text_edit()->add_color_override("selection_color", selection_color);
get_text_edit()->add_color_override("brace_mismatch_color", brace_mismatch_color);
get_text_edit()->add_color_override("current_line_color", current_line_color);
@ -346,6 +346,9 @@ void ShaderEditor::_menu_option(int p_option) {
goto_line_dialog->popup_find_line(shader_editor->get_text_edit());
} break;
case HELP_DOCS: {
OS::get_singleton()->shell_open("https://docs.godotengine.org/en/stable/tutorials/shading/shading_reference/index.html");
} break;
}
if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) {
shader_editor->get_text_edit()->call_deferred("grab_focus");
@ -577,10 +580,17 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_line"), SEARCH_GOTO_LINE);
search_menu->get_popup()->connect("id_pressed", this, "_menu_option");
help_menu = memnew(MenuButton);
help_menu->set_text(TTR("Help"));
help_menu->set_switch_on_hover(true);
help_menu->get_popup()->add_icon_item(p_node->get_gui_base()->get_icon("Instance", "EditorIcons"), TTR("Online Docs"), HELP_DOCS);
help_menu->get_popup()->connect("id_pressed", this, "_menu_option");
add_child(main_container);
main_container->add_child(hbc);
hbc->add_child(search_menu);
hbc->add_child(edit_menu);
hbc->add_child(help_menu);
hbc->add_style_override("panel", p_node->get_gui_base()->get_stylebox("ScriptEditorPanel", "EditorStyles"));
main_container->add_child(shader_editor);

View File

@ -88,12 +88,12 @@ class ShaderEditor : public PanelContainer {
SEARCH_FIND_PREV,
SEARCH_REPLACE,
SEARCH_GOTO_LINE,
HELP_DOCS,
};
MenuButton *edit_menu;
MenuButton *search_menu;
MenuButton *settings_menu;
MenuButton *help_menu;
PopupMenu *context_menu;
uint64_t idle;

View File

@ -5323,6 +5323,7 @@ void SpatialEditor::_register_all_gizmos() {
add_gizmo_plugin(Ref<VehicleWheelSpatialGizmoPlugin>(memnew(VehicleWheelSpatialGizmoPlugin)));
add_gizmo_plugin(Ref<VisibilityNotifierGizmoPlugin>(memnew(VisibilityNotifierGizmoPlugin)));
add_gizmo_plugin(Ref<ParticlesGizmoPlugin>(memnew(ParticlesGizmoPlugin)));
add_gizmo_plugin(Ref<CPUParticlesGizmoPlugin>(memnew(CPUParticlesGizmoPlugin)));
add_gizmo_plugin(Ref<ReflectionProbeGizmoPlugin>(memnew(ReflectionProbeGizmoPlugin)));
add_gizmo_plugin(Ref<GIProbeGizmoPlugin>(memnew(GIProbeGizmoPlugin)));
add_gizmo_plugin(Ref<BakedIndirectLightGizmoPlugin>(memnew(BakedIndirectLightGizmoPlugin)));

View File

@ -115,7 +115,7 @@ void TextEditor::_load_theme_settings() {
text_edit->add_color_override("line_number_color", line_number_color);
text_edit->add_color_override("caret_color", caret_color);
text_edit->add_color_override("caret_background_color", caret_background_color);
text_edit->add_color_override("font_selected_color", text_selected_color);
text_edit->add_color_override("font_color_selected", text_selected_color);
text_edit->add_color_override("selection_color", selection_color);
text_edit->add_color_override("brace_mismatch_color", brace_mismatch_color);
text_edit->add_color_override("current_line_color", current_line_color);

View File

@ -878,11 +878,9 @@ ThemeEditor::ThemeEditor() {
void ThemeEditorPlugin::edit(Object *p_node) {
if (Object::cast_to<Theme>(p_node)) {
theme_editor->show();
theme_editor->edit(Object::cast_to<Theme>(p_node));
} else {
theme_editor->edit(Ref<Theme>());
theme_editor->hide();
}
}
@ -897,11 +895,11 @@ void ThemeEditorPlugin::make_visible(bool p_visible) {
theme_editor->set_process(true);
button->show();
editor->make_bottom_panel_item_visible(theme_editor);
} else {
theme_editor->set_process(false);
if (theme_editor->is_visible_in_tree())
editor->hide_bottom_panel();
button->hide();
}
}

View File

@ -363,6 +363,8 @@ void TileMapEditor::_update_palette() {
// Update the palette
Vector<int> selected = get_selected_tiles();
int selected_single = palette->get_current();
int selected_manual = manual_palette->get_current();
palette->clear();
manual_palette->clear();
manual_palette->hide();
@ -470,7 +472,7 @@ void TileMapEditor::_update_palette() {
if (selected.get(0) != TileMap::INVALID_CELL) {
set_selected_tiles(selected);
sel_tile = selected.get(Math::rand() % selected.size());
} else {
} else if (palette->get_item_count() > 0) {
palette->select(0);
}
@ -511,9 +513,10 @@ void TileMapEditor::_update_palette() {
if (manual_palette->get_item_count() > 0) {
// Only show the manual palette if at least tile exists in it
int selected2 = manual_palette->get_current();
if (selected2 == -1) selected2 = 0;
manual_palette->set_current(selected2);
if (selected_manual == -1 || selected_single != palette->get_current())
selected_manual = 0;
if (selected_manual < manual_palette->get_item_count())
manual_palette->set_current(selected_manual);
manual_palette->show();
}
@ -1434,9 +1437,9 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
aabb.expand_to(node->world_to_map(xform_inv.xform(screen_size)));
Rect2i si = aabb.grow(1.0);
if (node->get_half_offset() != TileMap::HALF_OFFSET_X) {
if (node->get_half_offset() != TileMap::HALF_OFFSET_X && node->get_half_offset() != TileMap::HALF_OFFSET_NEGATIVE_X) {
int max_lines = 2000; //avoid crash if size too smal
int max_lines = 2000; //avoid crash if size too small
for (int i = (si.position.x) - 1; i <= (si.position.x + si.size.x); i++) {
@ -1450,7 +1453,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
}
} else {
int max_lines = 10000; //avoid crash if size too smal
int max_lines = 10000; //avoid crash if size too small
for (int i = (si.position.x) - 1; i <= (si.position.x + si.size.x); i++) {
@ -1458,7 +1461,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
Vector2 ofs;
if (ABS(j) & 1) {
ofs = cell_xf[0] * 0.5;
ofs = cell_xf[0] * (node->get_half_offset() == TileMap::HALF_OFFSET_X ? 0.5 : -0.5);
}
Vector2 from = xform.xform(node->map_to_world(Vector2(i, j), true) + ofs);
@ -1477,7 +1480,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
int max_lines = 10000; //avoid crash if size too smal
if (node->get_half_offset() != TileMap::HALF_OFFSET_Y) {
if (node->get_half_offset() != TileMap::HALF_OFFSET_Y && node->get_half_offset() != TileMap::HALF_OFFSET_NEGATIVE_Y) {
for (int i = (si.position.y) - 1; i <= (si.position.y + si.size.y); i++) {
@ -1498,7 +1501,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
Vector2 ofs;
if (ABS(j) & 1) {
ofs = cell_xf[1] * 0.5;
ofs = cell_xf[1] * (node->get_half_offset() == TileMap::HALF_OFFSET_Y ? 0.5 : -0.5);
}
Vector2 from = xform.xform(node->map_to_world(Vector2(j, i), true) + ofs);
@ -1539,8 +1542,12 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
for (int i = 0; i < 4; i++) {
if (node->get_half_offset() == TileMap::HALF_OFFSET_X && ABS(over_tile.y) & 1)
endpoints[i] += cell_xf[0] * 0.5;
if (node->get_half_offset() == TileMap::HALF_OFFSET_NEGATIVE_X && ABS(over_tile.y) & 1)
endpoints[i] += cell_xf[0] * -0.5;
if (node->get_half_offset() == TileMap::HALF_OFFSET_Y && ABS(over_tile.x) & 1)
endpoints[i] += cell_xf[1] * 0.5;
if (node->get_half_offset() == TileMap::HALF_OFFSET_NEGATIVE_Y && ABS(over_tile.x) & 1)
endpoints[i] += cell_xf[1] * -0.5;
endpoints[i] = xform.xform(endpoints[i]);
}
Color col;

View File

@ -1609,40 +1609,28 @@ void ProjectManager::_show_project(const String &p_path) {
OS::get_singleton()->shell_open(String("file://") + p_path);
}
void ProjectManager::_scan_dir(DirAccess *da, float pos, float total, List<String> *r_projects) {
List<String> subdirs;
void ProjectManager::_scan_dir(const String &path, List<String> *r_projects) {
DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
da->change_dir(path);
da->list_dir_begin();
String n = da->get_next();
while (n != String()) {
if (da->current_is_dir() && !n.begins_with(".")) {
subdirs.push_front(n);
_scan_dir(da->get_current_dir().plus_file(n), r_projects);
} else if (n == "project.godot") {
r_projects->push_back(da->get_current_dir());
}
n = da->get_next();
}
da->list_dir_end();
int m = 0;
for (List<String>::Element *E = subdirs.front(); E; E = E->next()) {
da->change_dir(E->get());
float slice = total / subdirs.size();
_scan_dir(da, pos + slice * m, slice, r_projects);
da->change_dir("..");
m++;
}
memdelete(da);
}
void ProjectManager::_scan_begin(const String &p_base) {
print_line("Scanning projects at: " + p_base);
List<String> projects;
DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
da->change_dir(p_base);
_scan_dir(da, 0, 1, &projects);
memdelete(da);
_scan_dir(p_base, &projects);
print_line("Found " + itos(projects.size()) + " projects.");
for (List<String>::Element *E = projects.front(); E; E = E->next()) {

View File

@ -102,7 +102,7 @@ class ProjectManager : public Control {
void _on_project_created(const String &dir);
void _on_projects_updated();
void _update_scroll_position(const String &dir);
void _scan_dir(DirAccess *da, float pos, float total, List<String> *r_projects);
void _scan_dir(const String &path, List<String> *r_projects);
void _install_project(const String &p_zip_path, const String &p_title);

View File

@ -36,6 +36,7 @@
#include "scene/3d/baked_lightmap.h"
#include "scene/3d/collision_polygon.h"
#include "scene/3d/collision_shape.h"
#include "scene/3d/cpu_particles.h"
#include "scene/3d/gi_probe.h"
#include "scene/3d/light.h"
#include "scene/3d/listener.h"
@ -571,9 +572,11 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point,
Transform orig_camera_transform = p_camera->get_camera_transform();
if (orig_camera_transform.origin.distance_squared_to(t.origin) > 0.01) {
if (orig_camera_transform.origin.distance_squared_to(t.origin) > 0.01 &&
ABS(orig_camera_transform.basis.get_axis(Vector3::AXIS_Z).dot(Vector3(0, 1, 0))) < 0.99) {
p_camera->look_at(t.origin, Vector3(0, 1, 0));
}
Vector3 c0 = t.xform(Vector3(selectable_icon_size, selectable_icon_size, 0) * scale);
Vector3 c1 = t.xform(Vector3(-selectable_icon_size, -selectable_icon_size, 0) * scale);
@ -582,7 +585,7 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point,
p_camera->set_global_transform(orig_camera_transform);
Rect2 rect(p0, p1 - p0);
Rect2 rect(p0, (p1 - p0).abs());
rect.set_position(center - rect.get_size() / 2.0);
@ -2373,6 +2376,33 @@ void VisibilityNotifierGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
////
CPUParticlesGizmoPlugin::CPUParticlesGizmoPlugin() {
create_icon_material("particles_icon", SpatialEditor::get_singleton()->get_icon("GizmoCPUParticles", "EditorIcons"));
}
bool CPUParticlesGizmoPlugin::has_gizmo(Spatial *p_spatial) {
return Object::cast_to<CPUParticles>(p_spatial) != NULL;
}
String CPUParticlesGizmoPlugin::get_name() const {
return "CPUParticles";
}
int CPUParticlesGizmoPlugin::get_priority() const {
return -1;
}
bool CPUParticlesGizmoPlugin::is_selectable_when_hidden() const {
return true;
}
void CPUParticlesGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
Ref<Material> icon = get_material("particles_icon", p_gizmo);
p_gizmo->add_unscaled_billboard(icon, 0.05);
}
////
ParticlesGizmoPlugin::ParticlesGizmoPlugin() {
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particles", Color(0.8, 0.7, 0.4));
create_material("particles_material", gizmo_color);

View File

@ -249,6 +249,18 @@ public:
VisibilityNotifierGizmoPlugin();
};
class CPUParticlesGizmoPlugin : public EditorSpatialGizmoPlugin {
GDCLASS(CPUParticlesGizmoPlugin, EditorSpatialGizmoPlugin);
public:
bool has_gizmo(Spatial *p_spatial);
String get_name() const;
int get_priority() const;
bool is_selectable_when_hidden() const;
void redraw(EditorSpatialGizmo *p_gizmo);
CPUParticlesGizmoPlugin();
};
class ParticlesGizmoPlugin : public EditorSpatialGizmoPlugin {
GDCLASS(ParticlesGizmoPlugin, EditorSpatialGizmoPlugin);

View File

@ -627,7 +627,8 @@ bool InputDefault::is_emulating_mouse_from_touch() const {
return emulate_mouse_from_touch;
}
Input::CursorShape InputDefault::get_default_cursor_shape() {
Input::CursorShape InputDefault::get_default_cursor_shape() const {
return default_shape;
}
@ -646,6 +647,11 @@ void InputDefault::set_default_cursor_shape(CursorShape p_shape) {
parse_input_event(mm);
}
Input::CursorShape InputDefault::get_current_cursor_shape() const {
return (Input::CursorShape)OS::get_singleton()->get_cursor_shape();
}
void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
if (Engine::get_singleton()->is_editor_hint())
return;
@ -653,21 +659,6 @@ void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_sh
OS::get_singleton()->set_custom_mouse_cursor(p_cursor, (OS::CursorShape)p_shape, p_hotspot);
}
void InputDefault::set_mouse_in_window(bool p_in_window) {
/* no longer supported, leaving this for reference to anyone who might want to implement hardware cursors
if (custom_cursor.is_valid()) {
if (p_in_window) {
set_mouse_mode(MOUSE_MODE_HIDDEN);
VisualServer::get_singleton()->cursor_set_visible(true);
} else {
set_mouse_mode(MOUSE_MODE_VISIBLE);
VisualServer::get_singleton()->cursor_set_visible(false);
}
}
*/
}
void InputDefault::accumulate_input_event(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());

View File

@ -243,10 +243,10 @@ public:
void set_emulate_mouse_from_touch(bool p_emulate);
virtual bool is_emulating_mouse_from_touch() const;
virtual CursorShape get_default_cursor_shape();
virtual CursorShape get_default_cursor_shape() const;
virtual void set_default_cursor_shape(CursorShape p_shape);
virtual CursorShape get_current_cursor_shape() const;
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = Input::CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
virtual void set_mouse_in_window(bool p_in_window);
void parse_mapping(String p_mapping);
void joy_button(int p_device, int p_button, bool p_pressed);

View File

@ -204,7 +204,8 @@ void finalize_physics() {
void Main::print_help(const char *p_binary) {
print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - https://godotengine.org");
print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
OS::get_singleton()->print("Free and open source software under the terms of the MIT license.\n");
OS::get_singleton()->print("(c) 2007-2019 Juan Linietsky, Ariel Manzur.\n");
OS::get_singleton()->print("(c) 2014-2019 Godot Engine contributors.\n");
OS::get_singleton()->print("\n");
@ -1087,6 +1088,9 @@ error:
Error Main::setup2(Thread::ID p_main_tid_override) {
// Print engine name and version
print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
if (p_main_tid_override) {
Thread::_main_thread_id = p_main_tid_override;
}

View File

@ -61,6 +61,7 @@ def update_version(module_version_string=""):
f.write("#define VERSION_BUILD \"" + str(build_name) + "\"\n")
f.write("#define VERSION_MODULE_CONFIG \"" + str(version.module_config) + module_version_string + "\"\n")
f.write("#define VERSION_YEAR " + str(version.year) + "\n")
f.write("#define VERSION_WEBSITE \"" + str(version.website) + "\"\n")
f.close()
# NOTE: It is safe to generate this file here, since this is still executed serially

View File

@ -162,8 +162,13 @@ $GODOT_HEAD_INCLUDE
requestAnimationFrame(animate);
function adjustCanvasDimensions() {
canvas.width = innerWidth;
canvas.height = innerHeight;
var scale = window.devicePixelRatio || 1;
var width = window.innerWidth;
var height = window.innerHeight;
canvas.width = width * scale;
canvas.height = height * scale;
canvas.style.width = width + "px";
canvas.style.height = height + "px";
}
animationCallbacks.push(adjustCanvasDimensions);
adjustCanvasDimensions();

View File

@ -2060,6 +2060,9 @@ CSGBrush *CSGPolygon::_build_brush() {
for (int i = 0; i <= splits; i++) {
float ofs = i * path_interval;
if (ofs > bl) {
ofs = bl;
}
if (i == splits && path_joined) {
ofs = 0.0;
}

View File

@ -243,7 +243,7 @@ void GDNativeLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_symbol_prefix", "symbol_prefix"), &GDNativeLibrary::set_symbol_prefix);
ClassDB::bind_method(D_METHOD("set_reloadable", "reloadable"), &GDNativeLibrary::set_reloadable);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "config_file", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile"), "set_config_file", "get_config_file");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "config_file", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile", 0), "set_config_file", "get_config_file");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "load_once"), "set_load_once", "should_load_once");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "singleton"), "set_singleton", "is_singleton");

View File

@ -99,16 +99,20 @@ public:
}
_FORCE_INLINE_ void set_load_once(bool p_load_once) {
config_file->set_value("general", "load_once", p_load_once);
load_once = p_load_once;
}
_FORCE_INLINE_ void set_singleton(bool p_singleton) {
config_file->set_value("general", "singleton", p_singleton);
singleton = p_singleton;
}
_FORCE_INLINE_ void set_symbol_prefix(String p_symbol_prefix) {
config_file->set_value("general", "symbol_prefix", p_symbol_prefix);
symbol_prefix = p_symbol_prefix;
}
_FORCE_INLINE_ void set_reloadable(bool p_reloadable) {
config_file->set_value("general", "reloadable", p_reloadable);
reloadable = p_reloadable;
}

View File

@ -518,7 +518,7 @@ void GDAPI godot_variant_evaluate(godot_variant_operator p_op, const godot_varia
const Variant *a = (const Variant *)p_a;
const Variant *b = (const Variant *)p_b;
Variant *ret = (Variant *)r_ret;
Variant::evaluate(op, a, b, *ret, *r_valid);
Variant::evaluate(op, *a, *b, *ret, *r_valid);
}
#ifdef __cplusplus

View File

@ -1309,7 +1309,7 @@ void NativeScriptLanguage::unregister_binding_functions(int p_idx) {
for (Set<Vector<void *> *>::Element *E = binding_instances.front(); E; E = E->next()) {
Vector<void *> &binding_data = *E->get();
if (binding_data[p_idx] && binding_functions[p_idx].second.free_instance_binding_data)
if (p_idx < binding_data.size() && binding_data[p_idx] && binding_functions[p_idx].second.free_instance_binding_data)
binding_functions[p_idx].second.free_instance_binding_data(binding_functions[p_idx].second.data, binding_data[p_idx]);
}
@ -1345,7 +1345,7 @@ void *NativeScriptLanguage::get_instance_binding_data(int p_idx, Object *p_objec
if (!(*binding_data)[p_idx]) {
const void *global_type_tag = global_type_tags[p_idx].get(p_object->get_class_name());
const void *global_type_tag = get_global_type_tag(p_idx, p_object->get_class_name());
// no binding data yet, soooooo alloc new one \o/
(*binding_data).write[p_idx] = binding_functions[p_idx].second.alloc_instance_binding_data(binding_functions[p_idx].second.data, global_type_tag, (godot_object *)p_object);
@ -1454,6 +1454,9 @@ const void *NativeScriptLanguage::get_global_type_tag(int p_idx, StringName p_cl
const HashMap<StringName, const void *> &tags = global_type_tags[p_idx];
if (!tags.has(p_class_name))
return NULL;
const void *tag = tags.get(p_class_name);
return tag;

View File

@ -1945,6 +1945,10 @@ String GDScriptWarning::get_message() const {
CHECK_SYMBOLS(1);
return "The local variable '" + symbols[0] + "' is declared but never used in the block.";
} break;
case SHADOWED_VARIABLE: {
CHECK_SYMBOLS(2);
return "The local variable '" + symbols[0] + "' is shadowing an already defined variable at line " + symbols[1] + ".";
} break;
case UNUSED_CLASS_VARIABLE: {
CHECK_SYMBOLS(1);
return "The class variable '" + symbols[0] + "' is declared but never used in the script.";
@ -2048,6 +2052,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
"UNASSIGNED_VARIABLE",
"UNASSIGNED_VARIABLE_OP_ASSIGN",
"UNUSED_VARIABLE",
"SHADOWED_VARIABLE",
"UNUSED_CLASS_VARIABLE",
"UNUSED_ARGUMENT",
"UNREACHABLE_CODE",
@ -2129,6 +2134,7 @@ GDScriptLanguage::GDScriptLanguage() {
#ifdef DEBUG_ENABLED
GLOBAL_DEF("debug/gdscript/warnings/enable", true);
GLOBAL_DEF("debug/gdscript/warnings/treat_warnings_as_errors", false);
GLOBAL_DEF("debug/gdscript/warnings/exclude_addons", true);
GLOBAL_DEF("debug/gdscript/completion/autocomplete_setters_and_getters", false);
for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower();

View File

@ -273,6 +273,7 @@ struct GDScriptWarning {
UNASSIGNED_VARIABLE, // Variable used but never assigned
UNASSIGNED_VARIABLE_OP_ASSIGN, // Variable never assigned but used in an assignment operation (+=, *=, etc)
UNUSED_VARIABLE, // Local variable is declared but never used
SHADOWED_VARIABLE, // Variable name shadowed by other variable
UNUSED_CLASS_VARIABLE, // Class variable is declared but never used in the file
UNUSED_ARGUMENT, // Function argument is never used
UNREACHABLE_CODE, // Code after a return statement

View File

@ -133,35 +133,13 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta
return NULL;
}
String GDScriptFunction::_get_call_error(const Variant::CallError &p_err, const String &p_where, const Variant **argptrs) const {
String err_text;
if (p_err.error == Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) {
int errorarg = p_err.argument;
err_text = "Invalid type in " + p_where + ". Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(p_err.expected) + ".";
} else if (p_err.error == Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
err_text = "Invalid call to " + p_where + ". Expected " + itos(p_err.argument) + " arguments.";
} else if (p_err.error == Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
err_text = "Invalid call to " + p_where + ". Expected " + itos(p_err.argument) + " arguments.";
} else if (p_err.error == Variant::CallError::CALL_ERROR_INVALID_METHOD) {
err_text = "Invalid call. Nonexistent " + p_where + ".";
} else if (p_err.error == Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
err_text = "Attempt to call " + p_where + " on a null instance.";
} else {
err_text = "Bug, call error: #" + itos(p_err.error);
}
return err_text;
}
#ifdef DEBUG_ENABLED
static String _get_var_type(const Variant *p_type) {
static String _get_var_type(const Variant *p_var) {
String basestr;
if (p_type->get_type() == Variant::OBJECT) {
Object *bobj = *p_type;
if (p_var->get_type() == Variant::OBJECT) {
Object *bobj = *p_var;
if (!bobj) {
basestr = "null instance";
} else {
@ -176,12 +154,42 @@ static String _get_var_type(const Variant *p_type) {
}
} else {
basestr = Variant::get_type_name(p_type->get_type());
basestr = Variant::get_type_name(p_var->get_type());
}
return basestr;
}
#endif
#endif // DEBUG_ENABLED
String GDScriptFunction::_get_call_error(const Variant::CallError &p_err, const String &p_where, const Variant **argptrs) const {
String err_text;
if (p_err.error == Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) {
int errorarg = p_err.argument;
// Handle the Object to Object case separately as we don't have further class details.
#ifdef DEBUG_ENABLED
if (p_err.expected == Variant::OBJECT && argptrs[errorarg]->get_type() == p_err.expected) {
err_text = "Invalid type in " + p_where + ". The Object-derived class of argument " + itos(errorarg + 1) + " (" + _get_var_type(argptrs[errorarg]) + ") is not a subclass of the expected argument class.";
} else
#endif // DEBUG_ENABLED
{
err_text = "Invalid type in " + p_where + ". Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(p_err.expected) + ".";
}
} else if (p_err.error == Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
err_text = "Invalid call to " + p_where + ". Expected " + itos(p_err.argument) + " arguments.";
} else if (p_err.error == Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
err_text = "Invalid call to " + p_where + ". Expected " + itos(p_err.argument) + " arguments.";
} else if (p_err.error == Variant::CallError::CALL_ERROR_INVALID_METHOD) {
err_text = "Invalid call. Nonexistent " + p_where + ".";
} else if (p_err.error == Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
err_text = "Attempt to call " + p_where + " on a null instance.";
} else {
err_text = "Bug, call error: #" + itos(p_err.error);
}
return err_text;
}
#if defined(__GNUC__)
#define OPCODES_TABLE \

View File

@ -5238,6 +5238,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) {
if (base_script.is_valid()) {
String ident = base;
Ref<GDScript> find_subclass = base_script;
for (int i = extend_iter; i < p_class->extends_class.size(); i++) {
@ -5247,7 +5248,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) {
if (base_script->get_subclasses().has(subclass)) {
base_script = base_script->get_subclasses()[subclass];
find_subclass = base_script->get_subclasses()[subclass];
} else if (base_script->get_constants().has(subclass)) {
Ref<GDScript> new_base_class = base_script->get_constants()[subclass];
@ -5255,7 +5256,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) {
_set_error("Constant is not a class: " + ident, p_class->line);
return;
}
base_script = new_base_class;
find_subclass = new_base_class;
} else {
_set_error("Could not find subclass: " + ident, p_class->line);
@ -5263,7 +5264,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) {
}
}
script = base_script;
script = find_subclass;
} else if (!base_class) {
@ -7661,6 +7662,11 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) {
if (p_function->arguments_usage[i] == 0 && !p_function->arguments[i].operator String().begins_with("_")) {
_add_warning(GDScriptWarning::UNUSED_ARGUMENT, p_function->line, p_function->name, p_function->arguments[i].operator String());
}
for (int j = 0; j < current_class->variables.size(); j++) {
if (current_class->variables[j].identifier == p_function->arguments[i]) {
_add_warning(GDScriptWarning::SHADOWED_VARIABLE, p_function->line, p_function->arguments[i], itos(current_class->variables[j].line));
}
}
#endif // DEBUG_ENABLED
}
@ -7734,6 +7740,17 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) {
p_function->return_type.has_type = false;
p_function->return_type.may_yield = true;
}
#ifdef DEBUG_ENABLED
for (Map<StringName, LocalVarNode *>::Element *E = p_function->body->variables.front(); E; E = E->next()) {
LocalVarNode *lv = E->get();
for (int i = 0; i < current_class->variables.size(); i++) {
if (current_class->variables[i].identifier == lv->name) {
_add_warning(GDScriptWarning::SHADOWED_VARIABLE, lv->line, lv->name, itos(current_class->variables[i].line));
}
}
}
#endif // DEBUG_ENABLED
}
void GDScriptParser::_check_class_blocks_types(ClassNode *p_class) {
@ -8163,6 +8180,9 @@ void GDScriptParser::_add_warning(int p_code, int p_line, const String &p_symbol
}
void GDScriptParser::_add_warning(int p_code, int p_line, const Vector<String> &p_symbols) {
if (GLOBAL_GET("debug/gdscript/warnings/exclude_addons").booleanize() && base_path.begins_with("res://addons/")) {
return;
}
if (tokenizer->is_ignoring_warnings() || !GLOBAL_GET("debug/gdscript/warnings/enable").booleanize()) {
return;
}

View File

@ -120,8 +120,8 @@ def configure(env):
else:
env.Append(LINKFLAGS=os.path.join(mono_lib_path, mono_static_lib_name + lib_suffix))
env.Append(LIBS='psapi')
env.Append(LIBS='version')
env.Append(LIBS=['psapi'])
env.Append(LIBS=['version'])
else:
mono_lib_name = find_file_in_dir(mono_lib_path, mono_lib_names, extension='.lib')
@ -131,7 +131,7 @@ def configure(env):
if env.msvc:
env.Append(LINKFLAGS=mono_lib_name + Environment()['LIBSUFFIX'])
else:
env.Append(LIBS=mono_lib_name)
env.Append(LIBS=[mono_lib_name])
mono_bin_path = os.path.join(mono_root, 'bin')

View File

@ -919,7 +919,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
}
#endif
void CSharpLanguage::project_assembly_loaded() {
void CSharpLanguage::_load_scripts_metadata() {
scripts_metadata.clear();
@ -953,6 +953,7 @@ void CSharpLanguage::project_assembly_loaded() {
}
scripts_metadata = old_dict_var.operator Dictionary();
scripts_metadata_invalidated = false;
print_verbose("Successfully loaded scripts metadata");
} else {
@ -1024,11 +1025,13 @@ bool CSharpLanguage::debug_break(const String &p_error, bool p_allow_continue) {
}
}
void CSharpLanguage::_uninitialize_script_bindings() {
void CSharpLanguage::_on_scripts_domain_unloaded() {
for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) {
CSharpScriptBinding &script_binding = E->value();
script_binding.inited = false;
}
scripts_metadata_invalidated = true;
}
void CSharpLanguage::set_language_index(int p_idx) {
@ -1086,6 +1089,8 @@ CSharpLanguage::CSharpLanguage() {
#endif
lang_idx = -1;
scripts_metadata_invalidated = true;
}
CSharpLanguage::~CSharpLanguage() {

View File

@ -309,14 +309,17 @@ class CSharpLanguage : public ScriptLanguage {
int lang_idx;
Dictionary scripts_metadata;
bool scripts_metadata_invalidated;
// For debug_break and debug_break_parse
int _debug_parse_err_line;
String _debug_parse_err_file;
String _debug_error;
void _load_scripts_metadata();
friend class GDMono;
void _uninitialize_script_bindings();
void _on_scripts_domain_unloaded();
public:
StringNameCache string_names;
@ -341,9 +344,15 @@ public:
void reload_assemblies(bool p_soft_reload);
#endif
void project_assembly_loaded();
_FORCE_INLINE_ Dictionary get_scripts_metadata_or_nothing() {
return scripts_metadata_invalidated ? Dictionary() : scripts_metadata;
}
_FORCE_INLINE_ const Dictionary &get_scripts_metadata() { return scripts_metadata; }
_FORCE_INLINE_ const Dictionary &get_scripts_metadata() {
if (scripts_metadata_invalidated)
_load_scripts_metadata();
return scripts_metadata;
}
virtual String get_name() const;

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="@C#" category="Core" version="3.1.1">
<class name="@C#" category="Core" version="3.1.2">
<brief_description>
</brief_description>
<description>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CSharpScript" inherits="Script" category="Core" version="3.1.1">
<class name="CSharpScript" inherits="Script" category="Core" version="3.1.2">
<brief_description>
</brief_description>
<description>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="GodotSharp" inherits="Object" category="Core" version="3.1.1">
<class name="GodotSharp" inherits="Object" category="Core" version="3.1.2">
<brief_description>
</brief_description>
<description>

View File

@ -158,7 +158,7 @@ Error generate_scripts_metadata(const String &p_project_path, const String &p_ou
PoolStringArray project_files = GDMonoMarshal::mono_array_to_PoolStringArray(ret);
PoolStringArray::Read r = project_files.read();
Dictionary old_dict = CSharpLanguage::get_singleton()->get_scripts_metadata();
Dictionary old_dict = CSharpLanguage::get_singleton()->get_scripts_metadata_or_nothing();
Dictionary new_dict;
for (int i = 0; i < project_files.size(); i++) {

View File

@ -121,25 +121,28 @@ void gdmono_debug_init() {
mono_debug_init(MONO_DEBUG_FORMAT_MONO);
CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8();
#ifdef TOOLS_ENABLED
int da_port = GLOBAL_DEF("mono/debugger_agent/port", 23685);
bool da_suspend = GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false);
int da_timeout = GLOBAL_DEF("mono/debugger_agent/wait_timeout", 3000);
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint() ||
ProjectSettings::get_singleton()->get_resource_path().empty() ||
Main::is_project_manager()) {
return;
}
#endif
CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8();
if (da_args.length() == 0) {
da_args = String("--debugger-agent=transport=dt_socket,address=127.0.0.1:" + itos(da_port) +
",embedding=1,server=y,suspend=" + (da_suspend ? "y,timeout=" + itos(da_timeout) : "n"))
.utf8();
}
#else
if (da_args.length() == 0)
return; // Exported games don't use the project settings to setup the debugger agent
#endif
// --debugger-agent=help
const char *options[] = {
@ -665,8 +668,6 @@ bool GDMono::_load_project_assembly() {
if (success) {
mono_assembly_set_main(project_assembly->get_assembly());
CSharpLanguage::get_singleton()->project_assembly_loaded();
} else {
if (OS::get_singleton()->is_stdout_verbose())
print_error("Mono: Failed to load project assembly");
@ -873,7 +874,7 @@ Error GDMono::reload_scripts_domain() {
}
}
CSharpLanguage::get_singleton()->_uninitialize_script_bindings();
CSharpLanguage::get_singleton()->_on_scripts_domain_unloaded();
Error err = _load_scripts_domain();
if (err != OK) {

View File

@ -33,6 +33,7 @@ if env['builtin_pcre2']:
"pcre2_newline.c",
"pcre2_ord2utf.c",
"pcre2_pattern_info.c",
"pcre2_script_run.c",
"pcre2_serialize.c",
"pcre2_string_utils.c",
"pcre2_study.c",

View File

@ -266,8 +266,8 @@ void AudioStreamOGGVorbis::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamOGGVorbis::get_loop_offset);
ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_loop", "has_loop");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "loop_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_loop_offset", "get_loop_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "loop_offset"), "set_loop_offset", "get_loop_offset");
}
AudioStreamOGGVorbis::AudioStreamOGGVorbis() {

View File

@ -23,10 +23,11 @@ if env['builtin_miniupnpc']:
"portlistingparse.c",
"upnpreplyparse.c",
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
thirdparty_sources = [thirdparty_dir + "miniupnpc/" + file for file in thirdparty_sources]
env_upnp.Append(CPPPATH=[thirdparty_dir])
env_upnp.Append(CPPFLAGS=["-DMINIUPNP_STATICLIB"])
env_upnp.Append(CPPFLAGS=["-DMINIUPNPC_SET_SOCKET_TIMEOUT"])
env_thirdparty = env_upnp.Clone()
env_thirdparty.disable_warnings()

View File

@ -45,15 +45,7 @@ bool VisualScriptNode::is_breakpoint() const {
return breakpoint;
}
void VisualScriptNode::_notification(int p_what) {
if (p_what == NOTIFICATION_POSTINITIALIZE) {
validate_input_default_values();
}
}
void VisualScriptNode::ports_changed_notify() {
validate_input_default_values();
emit_signal("ports_changed");
}
@ -272,11 +264,7 @@ void VisualScript::_node_ports_changed(int p_id) {
Function &func = functions[function];
Ref<VisualScriptNode> vsn = func.nodes[p_id].node;
if (OS::get_singleton()->get_main_loop() &&
Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop()) &&
Engine::get_singleton()->is_editor_hint()) {
vsn->validate_input_default_values(); //force validate default values when editing on editor
}
vsn->validate_input_default_values();
//must revalidate all the functions
@ -352,6 +340,7 @@ void VisualScript::add_node(const StringName &p_func, int p_id, const Ref<Visual
Ref<VisualScriptNode> vsn = p_node;
vsn->connect("ports_changed", this, "_node_ports_changed", varray(p_id));
vsn->scripts_used.insert(this);
vsn->validate_input_default_values(); // Validate when fully loaded
func.nodes[p_id] = nd;
}

View File

@ -54,7 +54,6 @@ class VisualScriptNode : public Resource {
void validate_input_default_values();
protected:
void _notification(int p_what);
void ports_changed_notify();
static void _bind_methods();

View File

@ -2040,7 +2040,7 @@ void VisualScriptEditor::set_edit_state(const Variant &p_state) {
Dictionary d = p_state;
if (d.has("function")) {
edited_func = p_state;
edited_func = d["function"];
selected = edited_func;
}

View File

@ -28,4 +28,4 @@ with open_utf8('register_platform_apis.gen.cpp', 'w') as f:
platform_sources.append('register_platform_apis.gen.cpp')
lib = env.add_library('platform', platform_sources)
env.Prepend(LIBS=lib)
env.Prepend(LIBS=[lib])

View File

@ -5,7 +5,7 @@ buildscript {
$$GRADLE_REPOSITORY_URLS$$
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.android.tools.build:gradle:3.4.2'
$$GRADLE_CLASSPATH$$
}
}

View File

@ -1,5 +1,7 @@
# Third party libraries
# Third-party libraries
This file list third-party libraries used in the Android source folder,
with their provenance and, when relevant, modifications made to those files.
## Google's vending library
@ -7,12 +9,13 @@
- Version: git (eb57657, 2018) with modifications
- License: Apache 2.0
Overwrite all files under `com/google/android/vending`
Overwrite all files under `com/google/android/vending`.
### Modify some files to avoid compile error and lint warning
Modify those files to avoid compile error and lint warning:
#### com/google/android/vending/licensing/util/Base64.java
```
- `com/google/android/vending/licensing/util/Base64.java`
```diff
@@ -338,7 +338,8 @@ public class Base64 {
e += 4;
}
@ -24,8 +27,9 @@ Overwrite all files under `com/google/android/vending`
}
```
#### com/google/android/vending/licensing/LicenseChecker.java
```
- `com/google/android/vending/licensing/LicenseChecker.java`
```diff
@@ -29,8 +29,8 @@ import android.os.RemoteException;
import android.provider.Settings.Secure;
import android.util.Log;
@ -37,11 +41,3 @@ Overwrite all files under `com/google/android/vending`
import com.google.android.vending.licensing.util.Base64;
import com.google.android.vending.licensing.util.Base64DecoderException;
```
```
@@ -287,13 +287,15 @@ public class LicenseChecker implements ServiceConnection {
if (logResponse) {
- String android_id = Secure.getString(mContext.getContentResolver(),
- Secure.ANDROID_ID);
+ String android_id = Secure.ANDROID_ID;
Date date = new Date();
```

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -746,7 +746,8 @@ public abstract class DownloaderService extends CustomIntentService implements I
public void run() {
setServiceRunning(true);
mNotification.onDownloadStateChanged(IDownloaderClient.STATE_FETCHING_URL);
String deviceId = Secure.ANDROID_ID;
String deviceId = Secure.getString(mContext.getContentResolver(),
Secure.ANDROID_ID);
final APKExpansionPolicy aep = new APKExpansionPolicy(mContext,
new AESObfuscator(getSALT(), mContext.getPackageName(), deviceId));

View File

@ -287,7 +287,8 @@ public class LicenseChecker implements ServiceConnection {
}
if (logResponse) {
String android_id = Secure.ANDROID_ID;
String android_id = Secure.getString(mContext.getContentResolver(),
Secure.ANDROID_ID);
Date date = new Date();
Log.d(TAG, "Server Failure: " + stringError);
Log.d(TAG, "Android ID: " + android_id);

View File

@ -287,14 +287,6 @@ bool OS_Android::can_draw() const {
return true; //always?
}
void OS_Android::set_cursor_shape(CursorShape p_shape) {
//android really really really has no mouse.. how amazing..
}
void OS_Android::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
}
void OS_Android::main_loop_begin() {
if (main_loop)

View File

@ -187,9 +187,6 @@ public:
virtual bool can_draw() const;
virtual void set_cursor_shape(CursorShape p_shape);
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
void main_loop_begin();
bool main_loop_iterate();
void main_loop_request_go_back();

View File

@ -203,6 +203,10 @@ void OS_Haiku::set_cursor_shape(CursorShape p_shape) {
//ERR_PRINT("set_cursor_shape() NOT IMPLEMENTED");
}
OS::CursorShape OS_Haiku::get_cursor_shape() const {
// TODO: implement get_cursor_shape
}
void OS_Haiku::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
// TODO
}

View File

@ -86,6 +86,7 @@ public:
virtual Point2 get_mouse_position() const;
virtual int get_mouse_button_state() const;
virtual void set_cursor_shape(CursorShape p_shape);
virtual CursorShape get_cursor_shape() const;
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
virtual int get_screen_count() const;

View File

@ -491,17 +491,11 @@ void OSIPhone::set_keep_screen_on(bool p_enabled) {
_set_keep_screen_on(p_enabled);
};
void OSIPhone::set_cursor_shape(CursorShape p_shape){
};
String OSIPhone::get_user_data_dir() const {
return data_dir;
};
void OSIPhone::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot){};
String OSIPhone::get_name() {
return "iOS";

View File

@ -167,9 +167,6 @@ public:
virtual void hide_virtual_keyboard();
virtual int get_virtual_keyboard_height() const;
virtual void set_cursor_shape(CursorShape p_shape);
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
virtual Size2 get_window_size() const;
virtual Rect2 get_window_safe_area() const;

View File

@ -39,6 +39,10 @@
- (void)didReceiveMemoryWarning;
- (void)viewDidLoad;
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures;
- (BOOL)prefersStatusBarHidden;
@end

View File

@ -83,6 +83,18 @@ int add_cmdline(int p_argc, char **p_args) {
printf("*********** did receive memory warning!\n");
};
- (void)viewDidLoad {
[super viewDidLoad];
if (@available(iOS 11.0, *)) {
[self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
}
}
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
return UIRectEdgeAll;
}
- (BOOL)shouldAutorotate {
switch (OS::get_singleton()->get_screen_orientation()) {
case OS::SCREEN_SENSOR:

View File

@ -70,6 +70,20 @@ static bool is_canvas_focused() {
/* clang-format on */
}
static Point2 correct_canvas_position(int x, int y) {
int canvas_width;
int canvas_height;
emscripten_get_canvas_element_size(NULL, &canvas_width, &canvas_height);
double element_width;
double element_height;
emscripten_get_element_css_size(NULL, &element_width, &element_height);
x = (int)(canvas_width / element_width * x);
y = (int)(canvas_height / element_height * y);
return Point2(x, y);
}
static bool cursor_inside_canvas = true;
EM_BOOL OS_JavaScript::fullscreen_change_callback(int p_event_type, const EmscriptenFullscreenChangeEvent *p_event, void *p_user_data) {
@ -285,7 +299,7 @@ EM_BOOL OS_JavaScript::mouse_button_callback(int p_event_type, const EmscriptenM
Ref<InputEventMouseButton> ev;
ev.instance();
ev->set_pressed(p_event_type == EMSCRIPTEN_EVENT_MOUSEDOWN);
ev->set_position(Point2(p_event->canvasX, p_event->canvasY));
ev->set_position(correct_canvas_position(p_event->canvasX, p_event->canvasY));
ev->set_global_position(ev->get_position());
dom2godot_mod(p_event, ev);
switch (p_event->button) {
@ -349,7 +363,7 @@ EM_BOOL OS_JavaScript::mousemove_callback(int p_event_type, const EmscriptenMous
OS_JavaScript *os = get_singleton();
int input_mask = os->input->get_mouse_button_mask();
Point2 pos = Point2(p_event->canvasX, p_event->canvasY);
Point2 pos = correct_canvas_position(p_event->canvasX, p_event->canvasY);
// For motion outside the canvas, only read mouse movement if dragging
// started inside the canvas; imitating desktop app behaviour.
if (!cursor_inside_canvas && !input_mask)
@ -666,7 +680,7 @@ EM_BOOL OS_JavaScript::touch_press_callback(int p_event_type, const EmscriptenTo
if (!touch.isChanged)
continue;
ev->set_index(touch.identifier);
ev->set_position(Point2(touch.canvasX, touch.canvasY));
ev->set_position(correct_canvas_position(touch.canvasX, touch.canvasY));
os->touches[i] = ev->get_position();
ev->set_pressed(p_event_type == EMSCRIPTEN_EVENT_TOUCHSTART);
@ -691,7 +705,7 @@ EM_BOOL OS_JavaScript::touchmove_callback(int p_event_type, const EmscriptenTouc
if (!touch.isChanged)
continue;
ev->set_index(touch.identifier);
ev->set_position(Point2(touch.canvasX, touch.canvasY));
ev->set_position(correct_canvas_position(touch.canvasX, touch.canvasY));
Point2 &prev = os->touches[i];
ev->set_relative(ev->get_position() - prev);
prev = ev->get_position();

View File

@ -172,6 +172,7 @@ public:
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false);
virtual void set_cursor_shape(CursorShape p_shape);
virtual CursorShape get_cursor_shape() const;
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
virtual void set_mouse_show(bool p_show);

View File

@ -714,8 +714,6 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
if (OS_OSX::singleton->main_loop && OS_OSX::singleton->mouse_mode != OS::MOUSE_MODE_CAPTURED)
OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
if (OS_OSX::singleton->input)
OS_OSX::singleton->input->set_mouse_in_window(false);
}
- (void)mouseEntered:(NSEvent *)event {
@ -723,8 +721,6 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
return;
if (OS_OSX::singleton->main_loop && OS_OSX::singleton->mouse_mode != OS::MOUSE_MODE_CAPTURED)
OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
if (OS_OSX::singleton->input)
OS_OSX::singleton->input->set_mouse_in_window(true);
OS::CursorShape p_shape = OS_OSX::singleton->cursor_shape;
OS_OSX::singleton->cursor_shape = OS::CURSOR_MAX;
@ -1700,6 +1696,11 @@ void OS_OSX::set_cursor_shape(CursorShape p_shape) {
cursor_shape = p_shape;
}
OS::CursorShape OS_OSX::get_cursor_shape() const {
return cursor_shape;
}
void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
if (p_cursor.is_valid()) {
Ref<Texture> texture = p_cursor;

Some files were not shown because too many files have changed in this diff Show More