Merge pull request #56731 from akien-mga/3.4-cherrypicks

This commit is contained in:
Rémi Verschelde 2022-01-12 19:21:25 +01:00 committed by GitHub
commit 02078f81fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 207 additions and 86 deletions

View File

@ -85,7 +85,7 @@ enum JoystickList {
JOY_BUTTON_20 = 20,
JOY_BUTTON_21 = 21,
JOY_BUTTON_22 = 22,
JOY_BUTTON_MAX = 23,
JOY_BUTTON_MAX = 128, // Android supports up to 36 buttons. DirectInput supports up to 128 buttons.
JOY_L = JOY_BUTTON_4,
JOY_R = JOY_BUTTON_5,

View File

@ -509,6 +509,9 @@ public:
}
Element *lower_bound(const T &p_value) const {
if (!_data._root) {
return nullptr;
}
return _lower_bound(p_value);
}

View File

@ -1006,8 +1006,11 @@
<constant name="JOY_BUTTON_22" value="22" enum="JoystickList">
Gamepad button 22.
</constant>
<constant name="JOY_BUTTON_MAX" value="23" enum="JoystickList">
Represents the maximum number of joystick buttons supported.
<constant name="JOY_BUTTON_MAX" value="128" enum="JoystickList">
The maximum number of game controller buttons supported by the engine. The actual limit may be lower on specific platforms:
- Android: Up to 36 buttons.
- Linux: Up to 80 buttons.
- Windows and macOS: Up to 128 buttons.
</constant>
<constant name="JOY_SONY_CIRCLE" value="1" enum="JoystickList">
DualShock circle button.

View File

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectRecord" inherits="AudioEffect" version="3.4">
<brief_description>
Audio effect used for recording sound from a microphone.
Audio effect used for recording the sound from an audio bus.
</brief_description>
<description>
Allows the user to record sound from a microphone. It sets and gets the format in which the audio file will be recorded (8-bit, 16-bit, or compressed). It checks whether or not the recording is active, and if it is, records the sound. It then returns the recorded sample.
Allows the user to record the sound from an audio bus. This can include all audio output by Godot when used on the "Master" audio bus.
Can be used (with an [AudioStreamMicrophone]) to record from a microphone.
It sets and gets the format in which the audio file will be recorded (8-bit, 16-bit, or compressed). It checks whether or not the recording is active, and if it is, records the sound. It then returns the recorded sample.
</description>
<tutorials>
<link title="Recording with microphone">https://docs.godotengine.org/en/3.4/tutorials/audio/recording_with_microphone.html</link>

View File

@ -846,6 +846,12 @@
<description>
Emitted when the mouse leaves the control's [code]Rect[/code] area, provided its [member mouse_filter] lets the event reach it.
[b]Note:[/b] [signal mouse_exited] will be emitted if the mouse enters a child [Control] node, even if the mouse cursor is still inside the parent's [code]Rect[/code] area.
If you want to check whether the mouse truly left the area, ignoring any top nodes, you can use code like this:
[codeblock]
func _on_mouse_exited():
if not Rect2(Vector2(), rect_size).has_point(get_local_mouse_position()):
# Not hovering over area.
[/codeblock]
</description>
</signal>
<signal name="resized">

View File

@ -13,7 +13,9 @@
<return type="void" />
<argument index="0" name="filter" type="String" />
<description>
Adds [code]filter[/code] as a custom filter; [code]filter[/code] should be of the form [code]"filename.extension ; Description"[/code]. For example, [code]"*.png ; PNG Images"[/code].
Adds [code]filter[/code] to the list of filters, which restricts what files can be picked.
A [code]filter[/code] should be of the form [code]"filename.extension ; Description"[/code], where filename and extension can be [code]*[/code] to match any string. Filters starting with [code].[/code] (i.e. empty filenames) are not allowed.
Example filters: [code]"*.png ; PNG Images"[/code], [code]"project.godot ; Godot Project"[/code].
</description>
</method>
<method name="clear_filters">
@ -65,7 +67,7 @@
</member>
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" override="true" default="false" />
<member name="filters" type="PoolStringArray" setter="set_filters" getter="get_filters" default="PoolStringArray( )">
The available file type filters. For example, this shows only [code].png[/code] and [code].gd[/code] files: [code]set_filters(PoolStringArray(["*.png ; PNG Images","*.gd ; GDScript Files"]))[/code].
The available file type filters. For example, this shows only [code].png[/code] and [code].gd[/code] files: [code]set_filters(PoolStringArray(["*.png ; PNG Images","*.gd ; GDScript Files"]))[/code]. Multiple file types can also be specified in a single filter. [code]"*.png, *.jpg, *.jpeg ; Supported Images"[/code] will show both PNG and JPEG files when selected.
</member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="FileDialog.Mode" default="4">
The dialog's open or save mode, which affects the selection behavior. See enum [code]Mode[/code] constants.

View File

@ -283,7 +283,7 @@
<theme_item name="port_grab_distance_horizontal" data_type="constant" type="int" default="24">
The horizontal range within which a port can be grabbed (on both sides).
</theme_item>
<theme_item name="port_grab_distance_vertical" data_type="constant" type="int" default="6">
<theme_item name="port_grab_distance_vertical" data_type="constant" type="int" default="26">
The vertical range within which a port can be grabbed (on both sides).
</theme_item>
<theme_item name="minimap" data_type="icon" type="Texture">

View File

@ -93,7 +93,7 @@
<argument index="1" name="edge" type="int" />
<description>
Returns specified edge associated with given face.
Edge argument must 2 or less because a face only has three edges.
Edge argument must be either 0, 1, or 2 because a face only has three edges.
</description>
</method>
<method name="get_face_meta" qualifiers="const">
@ -116,7 +116,7 @@
<argument index="1" name="vertex" type="int" />
<description>
Returns the specified vertex of the given face.
Vertex argument must be 2 or less because faces contain three vertices.
Vertex argument must be either 0, 1, or 2 because faces contain three vertices.
</description>
</method>
<method name="get_format" qualifiers="const">

View File

@ -17,7 +17,7 @@
</member>
<member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map">
The normal map that will be used if using the default [CanvasItemMaterial].
[b]Note:[/b] Godot expects the normal map to use X+, Y-, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
[b]Note:[/b] Godot expects the normal map to use X+, Y+, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
</member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture">
The [Texture] that will be used if using the default [CanvasItemMaterial]. Can be accessed as [code]TEXTURE[/code] in CanvasItem shader.

View File

@ -17,7 +17,7 @@
</member>
<member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map">
The normal map that will be used if using the default [CanvasItemMaterial].
[b]Note:[/b] Godot expects the normal map to use X+, Y-, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
[b]Note:[/b] Godot expects the normal map to use X+, Y+, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
</member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture">
The [Texture] that will be used if using the default [CanvasItemMaterial]. Can be accessed as [code]TEXTURE[/code] in CanvasItem shader.

View File

@ -7,6 +7,7 @@
3D particle node used to create a variety of particle systems and effects. [Particles] features an emitter that generates some number of particles at a given rate.
Use the [code]process_material[/code] property to add a [ParticlesMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles.
[b]Note:[/b] [Particles] only work when using the GLES3 renderer. If using the GLES2 renderer, use [CPUParticles] instead. You can convert [Particles] to [CPUParticles] by selecting the node, clicking the [b]Particles[/b] menu at the top of the 3D editor viewport then choosing [b]Convert to CPUParticles[/b].
[b]Note:[/b] On macOS, [Particles] rendering is much slower than [CPUParticles] due to transform feedback being implemented on the CPU instead of the GPU. Consider using [CPUParticles] instead when targeting macOS.
[b]Note:[/b] After working on a Particles node, remember to update its [member visibility_aabb] by selecting it, clicking the [b]Particles[/b] menu at the top of the 3D editor viewport then choose [b]Generate Visibility AABB[/b]. Otherwise, particles may suddenly disappear depending on the camera position and angle.
</description>
<tutorials>

View File

@ -7,6 +7,7 @@
2D particle node used to create a variety of particle systems and effects. [Particles2D] features an emitter that generates some number of particles at a given rate.
Use the [code]process_material[/code] property to add a [ParticlesMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles.
[b]Note:[/b] [Particles2D] only work when using the GLES3 renderer. If using the GLES2 renderer, use [CPUParticles2D] instead. You can convert [Particles2D] to [CPUParticles2D] by selecting the node, clicking the [b]Particles[/b] menu at the top of the 2D editor viewport then choosing [b]Convert to CPUParticles2D[/b].
[b]Note:[/b] On macOS, [Particles2D] rendering is much slower than [CPUParticles2D] due to transform feedback being implemented on the CPU instead of the GPU. Consider using [CPUParticles2D] instead when targeting macOS.
[b]Note:[/b] After working on a Particles node, remember to update its [member visibility_rect] by selecting it, clicking the [b]Particles[/b] menu at the top of the 2D editor viewport then choose [b]Generate Visibility Rect[/b]. Otherwise, particles may suddenly disappear depending on the camera position and angle.
[b]Note:[/b] Unlike [CPUParticles2D], [Particles2D] currently ignore the texture region defined in [AtlasTexture]s.
</description>

View File

@ -163,6 +163,7 @@
[codeblock]
ProjectSettings.set_setting("application/config/name", "Example")
[/codeblock]
This can also be used to erase custom project settings. To do this change the setting value to [code]null[/code].
</description>
</method>
</methods>

View File

@ -123,7 +123,7 @@
The custom color to use to draw the shape in the editor and at run-time if [b]Visible Collision Shapes[/b] is enabled in the [b]Debug[/b] menu. This color will be highlighted at run-time if the [RayCast] is colliding with something.
If set to [code]Color(0.0, 0.0, 0.0)[/code] (by default), the color set in [member ProjectSettings.debug/shapes/collision/shape_color] is used.
</member>
<member name="debug_shape_thickness" type="float" setter="set_debug_shape_thickness" getter="get_debug_shape_thickness" default="2.0">
<member name="debug_shape_thickness" type="int" setter="set_debug_shape_thickness" getter="get_debug_shape_thickness" default="2">
If set to [code]1[/code], a line is used as the debug shape. Otherwise, a truncated pyramid is drawn to represent the [RayCast]. Requires [b]Visible Collision Shapes[/b] to be enabled in the [b]Debug[/b] menu for the debug shape to be visible at run-time.
</member>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="false">

View File

@ -142,7 +142,7 @@
</member>
<member name="detail_normal" type="Texture" setter="set_texture" getter="get_texture">
Texture that specifies the per-pixel normal of the detail overlay.
[b]Note:[/b] Godot expects the normal map to use X+, Y-, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
[b]Note:[/b] Godot expects the normal map to use X+, Y+, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
</member>
<member name="detail_uv_layer" type="int" setter="set_detail_uv" getter="get_detail_uv" enum="SpatialMaterial.DetailUV">
Specifies whether to use [code]UV[/code] or [code]UV2[/code] for the detail layer. See [enum DetailUV] for options.
@ -235,7 +235,7 @@
<member name="normal_texture" type="Texture" setter="set_texture" getter="get_texture">
Texture used to specify the normal at a given pixel. The [code]normal_texture[/code] only uses the red and green channels; the blue and alpha channels are ignored. The normal read from [code]normal_texture[/code] is oriented around the surface normal provided by the [Mesh].
[b]Note:[/b] The mesh must have both normals and tangents defined in its vertex data. Otherwise, the normal map won't render correctly and will only appear to darken the whole surface. If creating geometry with [SurfaceTool], you can use [method SurfaceTool.generate_normals] and [method SurfaceTool.generate_tangents] to automatically generate normals and tangents respectively.
[b]Note:[/b] Godot expects the normal map to use X+, Y-, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
[b]Note:[/b] Godot expects the normal map to use X+, Y+, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
</member>
<member name="params_alpha_scissor_threshold" type="float" setter="set_alpha_scissor_threshold" getter="get_alpha_scissor_threshold">
Threshold at which the alpha scissor will discard values.

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="SpriteFrames" inherits="Resource" version="3.4">
<brief_description>
Sprite frame library for AnimatedSprite.
Sprite frame library for AnimatedSprite and AnimatedSprite3D.
</brief_description>
<description>
Sprite frame library for [AnimatedSprite]. Contains frames and animation data for playback.
Sprite frame library for an [AnimatedSprite] or [AnimatedSprite3D] node. Contains frames and animation data for playback.
[b]Note:[/b] You can associate a set of normal maps by creating additional [SpriteFrames] resources with a [code]_normal[/code] suffix. For example, having 2 [SpriteFrames] resources [code]run[/code] and [code]run_normal[/code] will make it so the [code]run[/code] animation uses the normal map.
</description>
<tutorials>

View File

@ -154,10 +154,11 @@
<argument index="2" name="flip_x" type="bool" default="false" />
<argument index="3" name="flip_y" type="bool" default="false" />
<argument index="4" name="transpose" type="bool" default="false" />
<argument index="5" name="autotile_coord" type="Vector2" default="Vector2( 0, 0 )" />
<description>
Sets the tile index for the cell given by a Vector2.
An index of [code]-1[/code] clears the cell.
Optionally, the tile can also be flipped or transposed.
Optionally, the tile can also be flipped, transposed, or given autotile coordinates. The autotile coordinate refers to the column and row of the subtile.
[b]Note:[/b] Data such as navigation polygons and collision shapes are not immediately updated for performance reasons.
If you need these to be immediately updated, you can call [method update_dirty_quadrants].
</description>

View File

@ -17,6 +17,7 @@
Many methods require a property name, such as [code]"position"[/code] above. You can find the correct property name by hovering over the property in the Inspector. You can also provide the components of a property directly by using [code]"property:component"[/code] (e.g. [code]position:x[/code]), where it would only apply to that particular component.
Many of the methods accept [code]trans_type[/code] and [code]ease_type[/code]. The first accepts an [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [url=https://easings.net/]easings.net[/url] for some examples). The second accepts an [enum EaseType] constant, and controls where the [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [constant EASE_IN_OUT], and use the one that looks best.
[url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/tween_cheatsheet.png]Tween easing and transition types cheatsheet[/url]
[b]Note:[/b] Tween methods will return [code]false[/code] if the requested operation cannot be completed.
</description>
<tutorials>
</tutorials>

View File

@ -948,6 +948,18 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
break;
}
if (tocopy->get_owner() != scene) {
accept->set_text(TTR("Can't save a branch which is a child of an already instantiated scene.\nTo save this branch into its own scene, open the original scene, right click on this branch, and select \"Save Branch as Scene\"."));
accept->popup_centered();
break;
}
if (scene->get_scene_inherited_state().is_valid() && scene->get_scene_inherited_state()->find_node_by_path(scene->get_path_to(tocopy)) >= 0) {
accept->set_text(TTR("Can't save a branch which is part of an inherited scene.\nTo save this branch into its own scene, open the original scene, right click on this branch, and select \"Save Branch as Scene\"."));
accept->popup_centered();
break;
}
new_scene_from_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
List<String> extensions;

View File

@ -775,7 +775,8 @@ InputDefault::InputDefault() {
void InputDefault::joy_button(int p_device, int p_button, bool p_pressed) {
_THREAD_SAFE_METHOD_;
Joypad &joy = joy_names[p_device];
//printf("got button %i, mapping is %i\n", p_button, joy.mapping);
ERR_FAIL_INDEX(p_button, JOY_BUTTON_MAX);
if (joy.last_buttons[p_button] == p_pressed) {
return;
}

View File

@ -377,6 +377,16 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
p_gizmo->add_lines(lines, material);
p_gizmo->add_collision_segments(lines);
Array csg_meshes = cs->get_meshes();
if (csg_meshes.size() != 2) {
return;
}
Ref<Mesh> csg_mesh = csg_meshes[1];
if (csg_mesh.is_valid()) {
p_gizmo->add_collision_triangles(csg_mesh->generate_triangle_mesh());
}
if (p_gizmo->is_selected()) {
// Draw a translucent representation of the CSG node
Ref<ArrayMesh> mesh = memnew(ArrayMesh);

View File

@ -1104,7 +1104,7 @@ HashMap<int, R> FBXMeshData::extract_per_vertex_data(
const int vertex_index = get_vertex_from_polygon_vertex(p_mesh_indices, polygon_vertex_index);
ERR_FAIL_COND_V_MSG(vertex_index < 0, (HashMap<int, R>()), "FBX file corrupted: #ERR05");
ERR_FAIL_COND_V_MSG(vertex_index >= p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR06");
const int index_to_direct = p_mapping_data.index[polygon_vertex_index];
const int index_to_direct = get_vertex_from_polygon_vertex(p_mapping_data.index, polygon_vertex_index);
T value = p_mapping_data.data[index_to_direct];
aggregate_vertex_data[vertex_index].push_back({ polygon_id, value });
}
@ -1309,7 +1309,7 @@ HashMap<int, T> FBXMeshData::extract_per_polygon(
} else {
ERR_FAIL_INDEX_V_MSG(polygon_index, (int)p_fbx_data.index.size(), (HashMap<int, T>()), "FBX file is corrupted: #ERR62");
const int index_to_direct = p_fbx_data.index[polygon_index];
const int index_to_direct = get_vertex_from_polygon_vertex(p_fbx_data.index, polygon_index);
T value = p_fbx_data.data[index_to_direct];
aggregate_polygon_data[polygon_index].push_back(value);
}

View File

@ -77,6 +77,17 @@ Object *GDScriptNativeClass::instance() {
return ClassDB::instance(name);
}
void GDScript::_clear_pending_func_states() {
GDScriptLanguage::get_singleton()->lock.lock();
while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) {
// Order matters since clearing the stack may already cause
// the GDSCriptFunctionState to be destroyed and thus removed from the list.
pending_func_states.remove(E);
E->self()->_clear_stack();
}
GDScriptLanguage::get_singleton()->lock.unlock();
}
GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error) {
/* STEP 1, CREATE */
@ -597,6 +608,7 @@ Error GDScript::reload(bool p_keep_state) {
for (Map<StringName, Ref<GDScript>>::Element *E = subclasses.front(); E; E = E->next()) {
_set_subclass_path(E->get(), path);
}
_clear_pending_func_states();
return OK;
}
@ -923,14 +935,7 @@ void GDScript::_save_orphaned_subclasses() {
}
GDScript::~GDScript() {
GDScriptLanguage::get_singleton()->lock.lock();
while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) {
// Order matters since clearing the stack may already cause
// the GDSCriptFunctionState to be destroyed and thus removed from the list.
pending_func_states.remove(E);
E->self()->_clear_stack();
}
GDScriptLanguage::get_singleton()->lock.unlock();
_clear_pending_func_states();
for (Map<StringName, GDScriptFunction *>::Element *E = member_functions.front(); E; E = E->next()) {
memdelete(E->get());

View File

@ -112,6 +112,7 @@ class GDScript : public Script {
SelfList<GDScript> script_list;
SelfList<GDScriptFunctionState>::List pending_func_states;
void _clear_pending_func_states();
GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error);

View File

@ -6595,103 +6595,110 @@ Error GLTFDocument::parse(Ref<GLTFState> state, String p_path, bool p_read_binar
state->major_version = version.get_slice(".", 0).to_int();
state->minor_version = version.get_slice(".", 1).to_int();
/* STEP 0 PARSE SCENE */
/* PARSE EXTENSIONS */
err = _parse_gltf_extensions(state);
if (err != OK) {
return Error::FAILED;
}
/* PARSE SCENE */
err = _parse_scenes(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 1 PARSE NODES */
/* PARSE NODES */
err = _parse_nodes(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 2 PARSE BUFFERS */
/* PARSE BUFFERS */
err = _parse_buffers(state, p_path.get_base_dir());
if (err != OK) {
return Error::FAILED;
}
/* STEP 3 PARSE BUFFER VIEWS */
/* PARSE BUFFER VIEWS */
err = _parse_buffer_views(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 4 PARSE ACCESSORS */
/* PARSE ACCESSORS */
err = _parse_accessors(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 5 PARSE IMAGES */
/* PARSE IMAGES */
err = _parse_images(state, p_path.get_base_dir());
if (err != OK) {
return Error::FAILED;
}
/* STEP 6 PARSE TEXTURES */
/* PARSE TEXTURES */
err = _parse_textures(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 7 PARSE TEXTURES */
/* PARSE TEXTURES */
err = _parse_materials(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 9 PARSE SKINS */
/* PARSE SKINS */
err = _parse_skins(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 10 DETERMINE SKELETONS */
/* DETERMINE SKELETONS */
err = _determine_skeletons(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 11 CREATE SKELETONS */
/* CREATE SKELETONS */
err = _create_skeletons(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 12 CREATE SKINS */
/* CREATE SKINS */
err = _create_skins(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 13 PARSE MESHES (we have enough info now) */
/* PARSE MESHES (we have enough info now) */
err = _parse_meshes(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 14 PARSE LIGHTS */
/* PARSE LIGHTS */
err = _parse_lights(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 15 PARSE CAMERAS */
/* PARSE CAMERAS */
err = _parse_cameras(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 16 PARSE ANIMATIONS */
/* PARSE ANIMATIONS */
err = _parse_animations(state);
if (err != OK) {
return Error::FAILED;
}
/* STEP 17 ASSIGN SCENE NAMES */
/* ASSIGN SCENE NAMES */
_assign_scene_names(state);
return OK;
@ -6811,3 +6818,15 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
}
return err;
}
Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> state) {
ERR_FAIL_COND_V(!state.is_valid(), ERR_PARSE_ERROR);
if (state->json.has("extensionsRequired") && state->json["extensionsRequired"].get_type() == Variant::ARRAY) {
Array extensions_required = state->json["extensionsRequired"];
if (extensions_required.find("KHR_draco_mesh_compression") != -1) {
ERR_PRINT("glTF2 extension KHR_draco_mesh_compression is not supported.");
return ERR_UNAVAILABLE;
}
}
return OK;
}

View File

@ -369,6 +369,8 @@ public:
String _sanitize_scene_name(Ref<GLTFState> state, const String &p_name);
String _legacy_validate_node_name(const String &p_name);
Error _parse_gltf_extensions(Ref<GLTFState> state);
void _process_mesh_instances(Ref<GLTFState> state, Node *scene_root);
void _generate_scene_node(Ref<GLTFState> state, Node *scene_parent,
Spatial *scene_root,

View File

@ -171,7 +171,7 @@ Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale)
{ 0 }, // R
{ 1, 0 }, // GR
{ 2, 1, 0 }, // BGR
{ 2, 1, 0, 3 } // BGRA
{ 3, 2, 1, 0 } // ABGR
};
int channel_count = get_channel_count(format);

View File

@ -67,7 +67,7 @@ void WebSocketServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_handshake_timeout"), &WebSocketServer::get_handshake_timeout);
ClassDB::bind_method(D_METHOD("set_handshake_timeout", "timeout"), &WebSocketServer::set_handshake_timeout);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handshake_timeout"), "set_handshake_timeout", "get_handshake_timeout");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "handshake_timeout"), "set_handshake_timeout", "get_handshake_timeout");
ADD_SIGNAL(MethodInfo("client_close_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "code"), PropertyInfo(Variant::STRING, "reason")));
ADD_SIGNAL(MethodInfo("client_disconnected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::BOOL, "was_clean_close")));

View File

@ -2991,6 +2991,13 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
debug_password = EditorSettings::get_singleton()->get("export/android/debug_keystore_pass");
debug_user = EditorSettings::get_singleton()->get("export/android/debug_keystore_user");
}
if (debug_keystore.is_rel_path()) {
debug_keystore = OS::get_singleton()->get_resource_dir().plus_file(debug_keystore).simplify_path();
}
if (!FileAccess::exists(debug_keystore)) {
EditorNode::add_io_error(TTR("Could not find keystore, unable to export."));
return ERR_FILE_CANT_OPEN;
}
cmdline.push_back("-Pdebug_keystore_file=" + debug_keystore); // argument to specify the debug keystore file.
cmdline.push_back("-Pdebug_keystore_alias=" + debug_user); // argument to specify the debug keystore alias.
@ -3000,6 +3007,9 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
String release_keystore = p_preset->get("keystore/release");
String release_username = p_preset->get("keystore/release_user");
String release_password = p_preset->get("keystore/release_password");
if (release_keystore.is_rel_path()) {
release_keystore = OS::get_singleton()->get_resource_dir().plus_file(release_keystore).simplify_path();
}
if (!FileAccess::exists(release_keystore)) {
EditorNode::add_io_error(TTR("Could not find keystore, unable to export."));
return ERR_FILE_CANT_OPEN;

View File

@ -170,9 +170,9 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
@implementation GodotApplicationDelegate
- (void)forceUnbundledWindowActivationHackStep1 {
// Step1: Switch focus to macOS Dock.
// Step 1: Switch focus to macOS SystemUIServer process.
// Required to perform step 2, TransformProcessType will fail if app is already the in focus.
for (NSRunningApplication *app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) {
for (NSRunningApplication *app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.systemuiserver"]) {
[app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
break;
}
@ -194,8 +194,8 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
- (void)applicationDidFinishLaunching:(NSNotification *)notice {
NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
if (nsappname == nil) {
// If executable is not a bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored).
if (nsappname == nil || isatty(STDOUT_FILENO) || isatty(STDIN_FILENO) || isatty(STDERR_FILENO)) {
// If the executable is started from terminal or is not bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored).
[self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02];
}
}

View File

@ -217,9 +217,9 @@ static _WinTranslatePair _vk_to_keycode[] = {
{ KEY_SLASH, VK_OEM_2 }, // (0xBF) //Windows 2000/XP: For the US standard keyboard, the '/?' key
{ KEY_QUOTELEFT, VK_OEM_3 }, // (0xC0)
{ KEY_BRACELEFT, VK_OEM_4 }, // (0xDB)
{ KEY_BRACKETLEFT, VK_OEM_4 }, // (0xDB)
{ KEY_BACKSLASH, VK_OEM_5 }, // (0xDC)
{ KEY_BRACERIGHT, VK_OEM_6 }, // (0xDD)
{ KEY_BRACKETRIGHT, VK_OEM_6 }, // (0xDD)
{ KEY_APOSTROPHE, VK_OEM_7 }, // (0xDE)
/*
{VK_OEM_8 (0xDF)

View File

@ -205,14 +205,23 @@ bool Particles2D::get_fractional_delta() const {
String Particles2D::get_configuration_warning() const {
String warning = Node2D::get_configuration_warning();
if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
if (warning != String()) {
warning += "\n\n";
}
warning += TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles\" option for this purpose.");
warning += "- " + TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles2D\" toolbar option for this purpose.");
return warning;
}
#ifdef OSX_ENABLED
if (warning != String()) {
warning += "\n\n";
}
warning += "- " + TTR("On macOS, Particles2D rendering is much slower than CPUParticles2D due to transform feedback being implemented on the CPU instead of the GPU.\nConsider using CPUParticles2D instead when targeting macOS.\nYou can use the \"Convert to CPUParticles2D\" toolbar option for this purpose.");
#endif
if (process_material.is_null()) {
if (warning != String()) {
warning += "\n\n";

View File

@ -636,7 +636,7 @@ void Polygon2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "uv"), "set_uv", "get_uv");
ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "vertex_colors"), "set_vertex_colors", "get_vertex_colors");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons"), "set_polygons", "get_polygons");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_bones", "_get_bones");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_bones", "_get_bones");
ADD_PROPERTY(PropertyInfo(Variant::INT, "internal_vertex_count", PROPERTY_HINT_RANGE, "0,1000"), "set_internal_vertex_count", "get_internal_vertex_count");
}

View File

@ -848,8 +848,8 @@ void TileMap::_make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool updat
}
}
void TileMap::set_cellv(const Vector2 &p_pos, int p_tile, bool p_flip_x, bool p_flip_y, bool p_transpose) {
set_cell(p_pos.x, p_pos.y, p_tile, p_flip_x, p_flip_y, p_transpose);
void TileMap::set_cellv(const Vector2 &p_pos, int p_tile, bool p_flip_x, bool p_flip_y, bool p_transpose, Vector2 p_autotile_coord) {
set_cell(p_pos.x, p_pos.y, p_tile, p_flip_x, p_flip_y, p_transpose, p_autotile_coord);
}
void TileMap::_set_celld(const Vector2 &p_pos, const Dictionary &p_data) {
@ -1811,7 +1811,7 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &TileMap::get_occluder_light_mask);
ClassDB::bind_method(D_METHOD("set_cell", "x", "y", "tile", "flip_x", "flip_y", "transpose", "autotile_coord"), &TileMap::set_cell, DEFVAL(false), DEFVAL(false), DEFVAL(false), DEFVAL(Vector2()));
ClassDB::bind_method(D_METHOD("set_cellv", "position", "tile", "flip_x", "flip_y", "transpose"), &TileMap::set_cellv, DEFVAL(false), DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_cellv", "position", "tile", "flip_x", "flip_y", "transpose", "autotile_coord"), &TileMap::set_cellv, DEFVAL(false), DEFVAL(false), DEFVAL(false), DEFVAL(Vector2()));
ClassDB::bind_method(D_METHOD("_set_celld", "position", "data"), &TileMap::_set_celld);
ClassDB::bind_method(D_METHOD("get_cell", "x", "y"), &TileMap::get_cell);
ClassDB::bind_method(D_METHOD("get_cellv", "position"), &TileMap::get_cellv);

View File

@ -263,7 +263,7 @@ public:
Vector2 get_cell_autotile_coord(int p_x, int p_y) const;
void _set_celld(const Vector2 &p_pos, const Dictionary &p_data);
void set_cellv(const Vector2 &p_pos, int p_tile, bool p_flip_x = false, bool p_flip_y = false, bool p_transpose = false);
void set_cellv(const Vector2 &p_pos, int p_tile, bool p_flip_x = false, bool p_flip_y = false, bool p_transpose = false, Vector2 p_autotile_coord = Vector2());
int get_cellv(const Vector2 &p_pos) const;
void make_bitmask_area_dirty(const Vector2 &p_pos);

View File

@ -212,11 +212,23 @@ bool Particles::get_fractional_delta() const {
}
String Particles::get_configuration_warning() const {
String warnings = GeometryInstance::get_configuration_warning();
if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles node instead. You can use the \"Convert to CPUParticles\" option for this purpose.");
if (warnings != String()) {
warnings += "\n\n";
}
warnings += "- " + TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles node instead. You can use the \"Convert to CPUParticles\" toolbar option for this purpose.");
return warnings;
}
String warnings = GeometryInstance::get_configuration_warning();
#ifdef OSX_ENABLED
if (warnings != String()) {
warnings += "\n\n";
}
warnings += "- " + TTR("On macOS, Particles rendering is much slower than CPUParticles due to transform feedback being implemented on the CPU instead of the GPU.\nConsider using CPUParticles instead when targeting macOS.\nYou can use the \"Convert to CPUParticles\" toolbar option for this purpose.");
#endif
bool meshes_found = false;
bool anim_material_found = false;

View File

@ -332,7 +332,7 @@ void RayCast::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_shape_thickness", PROPERTY_HINT_RANGE, "1,5"), "set_debug_shape_thickness", "get_debug_shape_thickness");
}
float RayCast::get_debug_shape_thickness() const {
int RayCast::get_debug_shape_thickness() const {
return debug_shape_thickness;
}
@ -361,7 +361,7 @@ void RayCast::_update_debug_shape_vertices() {
}
}
void RayCast::set_debug_shape_thickness(const float p_debug_shape_thickness) {
void RayCast::set_debug_shape_thickness(const int p_debug_shape_thickness) {
debug_shape_thickness = p_debug_shape_thickness;
update_gizmo();

View File

@ -100,8 +100,8 @@ public:
Ref<SpatialMaterial> get_debug_material();
float get_debug_shape_thickness() const;
void set_debug_shape_thickness(const float p_debug_thickness);
int get_debug_shape_thickness() const;
void set_debug_shape_thickness(const int p_debug_thickness);
void force_raycast_update();
bool is_colliding() const;

View File

@ -567,6 +567,7 @@ void FileDialog::clear_filters() {
invalidate();
}
void FileDialog::add_filter(const String &p_filter) {
ERR_FAIL_COND_MSG(p_filter.begins_with("."), "Filter must be \"filename.extension\", can't start with dot.");
filters.push_back(p_filter);
update_filters();
invalidate();

View File

@ -78,9 +78,7 @@ Size2 PopupMenu::get_minimum_size() const {
String text = items[i].xl_text;
size.width += font->get_string_size(text).width;
if (i > 0) {
size.height += vseparation;
}
size.height += vseparation;
if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) {
int accel_w = hseparation * 2;
@ -522,7 +520,9 @@ void PopupMenu::_notification(int p_what) {
}
for (int i = 0; i < items.size(); i++) {
if (i > 0) {
if (i == 0) {
ofs.y += vseparation / 2;
} else {
ofs.y += vseparation;
}
Point2 item_ofs = ofs;

View File

@ -374,7 +374,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
font_color_shadow = _find_color(text, p_font_color_shadow);
if (_find_underline(text) || (_find_meta(text, &meta) && underline_meta)) {
underline = true;
} else if (_find_strikethrough(text)) {
}
if (_find_strikethrough(text)) {
strikethrough = true;
}
@ -448,11 +449,18 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
line_descent = MAX(line_descent, descent);
fh = line_ascent + line_descent;
float align_spacing = 0.0f;
bool is_at_line_wrap = false;
if (end && c[end - 1] == ' ') {
if (align == ALIGN_FILL && p_mode != PROCESS_CACHE) {
int ln = MIN(l.offset_caches.size() - 1, line);
if (l.space_caches[ln]) {
align_ofs = spaces * l.offset_caches[ln] / l.space_caches[ln];
align_spacing = l.offset_caches[ln] / l.space_caches[ln];
align_ofs = spaces * align_spacing;
if (l.space_caches[ln] == spaces) {
is_at_line_wrap = true;
}
}
}
spaces++;
@ -613,24 +621,28 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
}
}
#ifdef TOOLS_ENABLED
const float line_width = EDSCALE;
#else
const float line_width = 1.0f;
#endif
if (underline) {
Color uc = color;
uc.a *= 0.5;
int uy = y + lh - line_descent + 2;
float underline_width = 1.0;
#ifdef TOOLS_ENABLED
underline_width *= EDSCALE;
#endif
VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + wofs, uy), p_ofs + Point2(align_ofs + wofs + w, uy), uc, underline_width);
} else if (strikethrough) {
const int line_y = y + lh - (line_descent - 2);
const Point2 from = p_ofs + Point2(align_ofs + wofs, line_y);
const Point2 to = from + Point2(w + (is_at_line_wrap ? 0 : align_spacing), 0);
VS::get_singleton()->canvas_item_add_line(ci, from, to, uc, line_width);
}
if (strikethrough) {
Color uc = color;
uc.a *= 0.5;
int uy = y + lh - (line_ascent + line_descent) / 2;
float strikethrough_width = 1.0;
#ifdef TOOLS_ENABLED
strikethrough_width *= EDSCALE;
#endif
VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + wofs, uy), p_ofs + Point2(align_ofs + wofs + w, uy), uc, strikethrough_width);
const int line_y = y + lh - (line_ascent + line_descent) / 2;
const Point2 from = p_ofs + Point2(align_ofs + wofs, line_y);
const Point2 to = from + Point2(w + (is_at_line_wrap ? 0 : align_spacing), 0);
VS::get_singleton()->canvas_item_add_line(ci, from, to, uc, line_width);
}
}
@ -1655,6 +1667,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub
_remove_item(p_item->subitems.front()->get(), p_line, p_subitem_line);
}
}
memdelete(p_item);
}
void RichTextLabel::add_image(const Ref<Texture> &p_image, const int p_width, const int p_height) {

View File

@ -382,6 +382,7 @@ void TextEdit::_update_scrollbars() {
cursor.line_ofs = 0;
cursor.wrap_ofs = 0;
v_scroll->set_value(0);
v_scroll->set_max(0);
v_scroll->hide();
}
@ -399,6 +400,7 @@ void TextEdit::_update_scrollbars() {
} else {
cursor.x_ofs = 0;
h_scroll->set_value(0);
h_scroll->set_max(0);
h_scroll->hide();
}

View File

@ -903,7 +903,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// Visual Node Ports
theme->set_constant("port_grab_distance_horizontal", "GraphEdit", 24 * scale);
theme->set_constant("port_grab_distance_vertical", "GraphEdit", 6 * scale);
theme->set_constant("port_grab_distance_vertical", "GraphEdit", 26 * scale);
theme->set_stylebox("bg", "GraphEditMinimap", make_flat_stylebox(Color(0.24, 0.24, 0.24), 0, 0, 0, 0));
Ref<StyleBoxFlat> style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0);

View File

@ -2353,6 +2353,9 @@ void TextureLayered::create(uint32_t p_width, uint32_t p_height, uint32_t p_dept
void TextureLayered::set_layer_data(const Ref<Image> &p_image, int p_layer) {
ERR_FAIL_COND(!texture.is_valid());
ERR_FAIL_COND(!p_image.is_valid());
ERR_FAIL_COND_MSG(
p_image->get_width() > width || p_image->get_height() > height,
vformat("Image size(%dx%d) is bigger than texture size (%dx%d).", p_image->get_width(), p_image->get_height(), width, height));
VS::get_singleton()->texture_set_data(texture, p_image, p_layer);
}