Merge pull request #61093 from akien-mga/3.x-cherrypicks
Cherry-picks for the 3.x branch (future 3.5) - 21st batch
This commit is contained in:
commit
b62ed1f005
2
.github/workflows/javascript_builds.yml
vendored
2
.github/workflows/javascript_builds.yml
vendored
@ -5,7 +5,7 @@ on: [push, pull_request]
|
||||
env:
|
||||
GODOT_BASE_BRANCH: 3.x
|
||||
SCONSFLAGS: verbose=yes warnings=all werror=yes debug_symbols=no
|
||||
EM_VERSION: 2.0.25
|
||||
EM_VERSION: 3.1.10
|
||||
EM_CACHE_FOLDER: "emsdk-cache"
|
||||
|
||||
concurrency:
|
||||
|
@ -370,7 +370,7 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p
|
||||
const uint8_t *rofs = &p_src[((y * p_width) + x) * (read_bytes + (read_alpha ? 1 : 0))];
|
||||
uint8_t *wofs = &p_dst[((y * p_width) + x) * (write_bytes + (write_alpha ? 1 : 0))];
|
||||
|
||||
uint8_t rgba[4];
|
||||
uint8_t rgba[4] = { 0, 0, 0, 255 };
|
||||
|
||||
if (read_gray) {
|
||||
rgba[0] = rofs[0];
|
||||
@ -388,7 +388,7 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p
|
||||
|
||||
if (write_gray) {
|
||||
//TODO: not correct grayscale, should use fixed point version of actual weights
|
||||
wofs[0] = uint8_t((uint16_t(rofs[0]) + uint16_t(rofs[1]) + uint16_t(rofs[2])) / 3);
|
||||
wofs[0] = uint8_t((uint16_t(rgba[0]) + uint16_t(rgba[1]) + uint16_t(rgba[2])) / 3);
|
||||
} else {
|
||||
for (uint32_t i = 0; i < write_bytes; i++) {
|
||||
wofs[i] = rgba[i];
|
||||
@ -1733,12 +1733,14 @@ PoolVector<uint8_t> Image::get_data() const {
|
||||
}
|
||||
|
||||
void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
|
||||
ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0.");
|
||||
ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0.");
|
||||
ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + ".");
|
||||
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + ".");
|
||||
ERR_FAIL_COND_MSG(p_width <= 0, "The Image width specified (" + itos(p_width) + " pixels) must be greater than 0 pixels.");
|
||||
ERR_FAIL_COND_MSG(p_height <= 0, "The Image height specified (" + itos(p_height) + " pixels) must be greater than 0 pixels.");
|
||||
ERR_FAIL_COND_MSG(p_width > MAX_WIDTH,
|
||||
"The Image width specified (" + itos(p_width) + " pixels) cannot be greater than " + itos(MAX_WIDTH) + "pixels.");
|
||||
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT,
|
||||
"The Image height specified (" + itos(p_height) + " pixels) cannot be greater than " + itos(MAX_HEIGHT) + "pixels.");
|
||||
ERR_FAIL_COND_MSG(write_lock.ptr(), "Cannot create image when it is locked.");
|
||||
ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "Image format out of range, please see Image's Format enum.");
|
||||
ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "The Image format specified (" + itos(p_format) + ") is out of range. See Image's Format enum.");
|
||||
|
||||
int mm = 0;
|
||||
int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
|
||||
@ -1755,16 +1757,32 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma
|
||||
}
|
||||
|
||||
void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data) {
|
||||
ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0.");
|
||||
ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0.");
|
||||
ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + ".");
|
||||
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + ".");
|
||||
ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "Image format out of range, please see Image's Format enum.");
|
||||
ERR_FAIL_COND_MSG(p_width <= 0, "The Image width specified (" + itos(p_width) + " pixels) must be greater than 0 pixels.");
|
||||
ERR_FAIL_COND_MSG(p_height <= 0, "The Image height specified (" + itos(p_height) + " pixels) must be greater than 0 pixels.");
|
||||
ERR_FAIL_COND_MSG(p_width > MAX_WIDTH,
|
||||
"The Image width specified (" + itos(p_width) + " pixels) cannot be greater than " + itos(MAX_WIDTH) + " pixels.");
|
||||
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT,
|
||||
"The Image height specified (" + itos(p_height) + " pixels) cannot be greater than " + itos(MAX_HEIGHT) + " pixels.");
|
||||
ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "The Image format specified (" + itos(p_format) + ") is out of range. See Image's Format enum.");
|
||||
|
||||
int mm;
|
||||
int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
|
||||
|
||||
ERR_FAIL_COND_MSG(p_data.size() != size, "Expected data size of " + itos(size) + " bytes in Image::create(), got instead " + itos(p_data.size()) + " bytes.");
|
||||
if (unlikely(p_data.size() != size)) {
|
||||
String description_mipmaps;
|
||||
if (p_use_mipmaps) {
|
||||
const int num_mipmaps = get_image_required_mipmaps(p_width, p_height, p_format);
|
||||
if (num_mipmaps != 1) {
|
||||
description_mipmaps = vformat("with %d mipmaps", num_mipmaps);
|
||||
} else {
|
||||
description_mipmaps = "with 1 mipmap";
|
||||
}
|
||||
} else {
|
||||
description_mipmaps = "without mipmaps";
|
||||
}
|
||||
const String description = vformat("%dx%dx%d (%s)", p_width, p_height, get_format_pixel_size(p_format), description_mipmaps);
|
||||
ERR_FAIL_MSG(vformat("Expected Image data size of %s = %d bytes, got %d bytes instead.", description, size, p_data.size()));
|
||||
}
|
||||
|
||||
height = p_height;
|
||||
width = p_width;
|
||||
|
@ -271,7 +271,7 @@ static int _bsp_find_best_half_plane(const Face3 *p_faces, const Vector<int> &p_
|
||||
const Face3 &f = p_faces[indices[i]];
|
||||
Plane p = f.get_plane();
|
||||
|
||||
int num_over = 0, num_under = 0, num_spanning = 0;
|
||||
int num_over = 0, num_under = 0; //num_spanning = 0;
|
||||
|
||||
for (int j = 0; j < ic; j++) {
|
||||
if (i == j) {
|
||||
@ -294,7 +294,7 @@ static int _bsp_find_best_half_plane(const Face3 *p_faces, const Vector<int> &p_
|
||||
}
|
||||
|
||||
if (over && under) {
|
||||
num_spanning++;
|
||||
//num_spanning++;
|
||||
} else if (over) {
|
||||
num_over++;
|
||||
} else {
|
||||
|
@ -394,7 +394,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
|
||||
if (O->get().plane.is_equal_approx(f.plane)) {
|
||||
//merge and delete edge and contiguous face, while repointing edges (uuugh!)
|
||||
int ois = O->get().indices.size();
|
||||
int merged = 0;
|
||||
|
||||
for (int j = 0; j < ois; j++) {
|
||||
//search a
|
||||
@ -409,7 +408,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
|
||||
if (idx != a) {
|
||||
f.indices.insert(i + 1, idx);
|
||||
i++;
|
||||
merged++;
|
||||
}
|
||||
Edge e2(idx, idxn);
|
||||
|
||||
|
@ -261,7 +261,7 @@ String Time::get_time_string_from_unix_time(int64_t p_unix_time_val) const {
|
||||
return vformat("%02d:%02d:%02d", hour, minute, second);
|
||||
}
|
||||
|
||||
Dictionary Time::get_datetime_dict_from_string(String p_datetime, bool p_weekday) const {
|
||||
Dictionary Time::get_datetime_dict_from_datetime_string(String p_datetime, bool p_weekday) const {
|
||||
PARSE_ISO8601_STRING(Dictionary())
|
||||
Dictionary dict;
|
||||
dict[YEAR_KEY] = year;
|
||||
@ -279,7 +279,7 @@ Dictionary Time::get_datetime_dict_from_string(String p_datetime, bool p_weekday
|
||||
return dict;
|
||||
}
|
||||
|
||||
String Time::get_datetime_string_from_dict(const Dictionary p_datetime, bool p_use_space) const {
|
||||
String Time::get_datetime_string_from_datetime_dict(const Dictionary p_datetime, bool p_use_space) const {
|
||||
ERR_FAIL_COND_V_MSG(p_datetime.empty(), "", "Invalid datetime Dictionary: Dictionary is empty.");
|
||||
EXTRACT_FROM_DICTIONARY
|
||||
VALIDATE_YMDHMS("")
|
||||
@ -410,8 +410,8 @@ void Time::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_datetime_string_from_unix_time", "unix_time_val", "use_space"), &Time::get_datetime_string_from_unix_time, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("get_date_string_from_unix_time", "unix_time_val"), &Time::get_date_string_from_unix_time);
|
||||
ClassDB::bind_method(D_METHOD("get_time_string_from_unix_time", "unix_time_val"), &Time::get_time_string_from_unix_time);
|
||||
ClassDB::bind_method(D_METHOD("get_datetime_dict_from_string", "datetime", "weekday"), &Time::get_datetime_dict_from_string);
|
||||
ClassDB::bind_method(D_METHOD("get_datetime_string_from_dict", "datetime", "use_space"), &Time::get_datetime_string_from_dict);
|
||||
ClassDB::bind_method(D_METHOD("get_datetime_dict_from_datetime_string", "datetime", "weekday"), &Time::get_datetime_dict_from_datetime_string);
|
||||
ClassDB::bind_method(D_METHOD("get_datetime_string_from_datetime_dict", "datetime", "use_space"), &Time::get_datetime_string_from_datetime_dict);
|
||||
ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime_dict", "datetime"), &Time::get_unix_time_from_datetime_dict);
|
||||
ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime_string", "datetime"), &Time::get_unix_time_from_datetime_string);
|
||||
ClassDB::bind_method(D_METHOD("get_offset_string_from_offset_minutes", "offset_minutes"), &Time::get_offset_string_from_offset_minutes);
|
||||
|
@ -85,8 +85,8 @@ public:
|
||||
String get_datetime_string_from_unix_time(int64_t p_unix_time_val, bool p_use_space = false) const;
|
||||
String get_date_string_from_unix_time(int64_t p_unix_time_val) const;
|
||||
String get_time_string_from_unix_time(int64_t p_unix_time_val) const;
|
||||
Dictionary get_datetime_dict_from_string(String p_datetime, bool p_weekday = true) const;
|
||||
String get_datetime_string_from_dict(const Dictionary p_datetime, bool p_use_space = false) const;
|
||||
Dictionary get_datetime_dict_from_datetime_string(String p_datetime, bool p_weekday = true) const;
|
||||
String get_datetime_string_from_datetime_dict(const Dictionary p_datetime, bool p_use_space = false) const;
|
||||
int64_t get_unix_time_from_datetime_dict(const Dictionary p_datetime) const;
|
||||
int64_t get_unix_time_from_datetime_string(String p_datetime) const;
|
||||
String get_offset_string_from_offset_minutes(int64_t p_offset_minutes) const;
|
||||
|
@ -1069,6 +1069,20 @@ ProjectSettings::ProjectSettings() {
|
||||
GLOBAL_DEF("application/config/use_custom_user_dir", false);
|
||||
GLOBAL_DEF("application/config/custom_user_dir_name", "");
|
||||
GLOBAL_DEF("application/config/project_settings_override", "");
|
||||
|
||||
GLOBAL_DEF("display/window/size/width", 1024);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/width", PropertyInfo(Variant::INT, "display/window/size/width", PROPERTY_HINT_RANGE, "0,7680,1,or_greater")); // 8K resolution
|
||||
GLOBAL_DEF("display/window/size/height", 600);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/height", PropertyInfo(Variant::INT, "display/window/size/height", PROPERTY_HINT_RANGE, "0,4320,1,or_greater")); // 8K resolution
|
||||
GLOBAL_DEF("display/window/size/resizable", true);
|
||||
GLOBAL_DEF("display/window/size/borderless", false);
|
||||
GLOBAL_DEF("display/window/size/fullscreen", false);
|
||||
GLOBAL_DEF("display/window/size/always_on_top", false);
|
||||
GLOBAL_DEF("display/window/size/test_width", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_width", PropertyInfo(Variant::INT, "display/window/size/test_width", PROPERTY_HINT_RANGE, "0,7680,1,or_greater")); // 8K resolution
|
||||
GLOBAL_DEF("display/window/size/test_height", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_height", PropertyInfo(Variant::INT, "display/window/size/test_height", PROPERTY_HINT_RANGE, "0,4320,1,or_greater")); // 8K resolution
|
||||
|
||||
GLOBAL_DEF("audio/default_bus_layout", "res://default_bus_layout.tres");
|
||||
custom_prop_info["audio/default_bus_layout"] = PropertyInfo(Variant::STRING, "audio/default_bus_layout", PROPERTY_HINT_FILE, "*.tres");
|
||||
|
||||
|
@ -157,6 +157,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
|
||||
return OK;
|
||||
}
|
||||
if (ch == '\n') {
|
||||
line++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1457,6 +1458,7 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r
|
||||
return ERR_FILE_EOF;
|
||||
}
|
||||
if (ch == '\n') {
|
||||
line++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="AnimatedSprite" inherits="Node2D" version="3.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
Sprite node that can use multiple textures for animation.
|
||||
Sprite node that contains multiple textures as frames to play for animation.
|
||||
</brief_description>
|
||||
<description>
|
||||
Animations are created using a [SpriteFrames] resource, which can be configured in the editor via the SpriteFrames panel.
|
||||
[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.
|
||||
[AnimatedSprite] is similar to the [Sprite] node, except it carries multiple textures as animation frames. Animations are created using a [SpriteFrames] resource, which allows you to import image files (or a folder containing said files) to provide the animation frames for the sprite. The [SpriteFrames] resource can be configured in the editor via the SpriteFrames bottom panel.
|
||||
[b]Note:[/b] You can associate a set of normal or specular maps by creating additional [SpriteFrames] resources with a [code]_normal[/code] or [code]_specular[/code] suffix. For example, having 3 [SpriteFrames] resources [code]run[/code], [code]run_normal[/code], and [code]run_specular[/code] will make it so the [code]run[/code] animation uses normal and specular maps.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="2D Sprite animation">$DOCS_URL/tutorials/2d/2d_sprite_animation.html</link>
|
||||
@ -29,7 +29,7 @@
|
||||
</methods>
|
||||
<members>
|
||||
<member name="animation" type="String" setter="set_animation" getter="get_animation" default=""default"">
|
||||
The current animation from the [code]frames[/code] resource. If this value changes, the [code]frame[/code] counter is reset.
|
||||
The current animation from the [member frames] resource. If this value changes, the [code]frame[/code] counter is reset.
|
||||
</member>
|
||||
<member name="centered" type="bool" setter="set_centered" getter="is_centered" default="true">
|
||||
If [code]true[/code], texture will be centered.
|
||||
@ -44,7 +44,7 @@
|
||||
The displayed animation frame's index.
|
||||
</member>
|
||||
<member name="frames" type="SpriteFrames" setter="set_sprite_frames" getter="get_sprite_frames">
|
||||
The [SpriteFrames] resource containing the animation(s).
|
||||
The [SpriteFrames] resource containing the animation(s). Allows you the option to load, edit, clear, make unique and save the states of the [SpriteFrames] resource.
|
||||
</member>
|
||||
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2( 0, 0 )">
|
||||
The texture's drawing offset.
|
||||
|
@ -159,6 +159,7 @@
|
||||
<argument index="1" name="update" type="bool" default="false" />
|
||||
<description>
|
||||
Seeks the animation to the [code]seconds[/code] point in time (in seconds). If [code]update[/code] is [code]true[/code], the animation updates too, otherwise it updates at process time. Events between the current frame and [code]seconds[/code] are skipped.
|
||||
[b]Note:[/b] Seeking to the end of the animation doesn't emit [signal animation_finished]. If you want to skip animation and emit the signal, use [method advance].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_blend_time">
|
||||
|
@ -75,14 +75,14 @@
|
||||
<return type="Vector3" />
|
||||
<argument index="0" name="screen_point" type="Vector2" />
|
||||
<description>
|
||||
Returns a normal vector in world space, that is the result of projecting a point on the [Viewport] rectangle by the camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking.
|
||||
Returns a normal vector in world space, that is the result of projecting a point on the [Viewport] rectangle by the inverse camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking.
|
||||
</description>
|
||||
</method>
|
||||
<method name="project_ray_origin" qualifiers="const">
|
||||
<return type="Vector3" />
|
||||
<argument index="0" name="screen_point" type="Vector2" />
|
||||
<description>
|
||||
Returns a 3D position in world space, that is the result of projecting a point on the [Viewport] rectangle by the camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking.
|
||||
Returns a 3D position in world space, that is the result of projecting a point on the [Viewport] rectangle by the inverse camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_cull_mask_bit">
|
||||
|
@ -19,6 +19,7 @@
|
||||
</member>
|
||||
<member name="one_way_collision" type="bool" setter="set_one_way_collision" getter="is_one_way_collision_enabled" default="false">
|
||||
If [code]true[/code], only edges that face up, relative to [CollisionPolygon2D]'s rotation, will collide with other objects.
|
||||
[b]Note:[/b] This property has no effect if this [CollisionPolygon2D] is a child of an [Area2D] node.
|
||||
</member>
|
||||
<member name="one_way_collision_margin" type="float" setter="set_one_way_collision_margin" getter="get_one_way_collision_margin" default="1.0">
|
||||
The margin used for one-way collision (in pixels). Higher values will make the shape thicker, and work better for colliders that enter the polygon at a high velocity.
|
||||
|
@ -20,6 +20,7 @@
|
||||
</member>
|
||||
<member name="one_way_collision" type="bool" setter="set_one_way_collision" getter="is_one_way_collision_enabled" default="false">
|
||||
Sets whether this collision shape should only detect collision on one side (top or bottom).
|
||||
[b]Note:[/b] This property has no effect if this [CollisionShape2D] is a child of an [Area2D] node.
|
||||
</member>
|
||||
<member name="one_way_collision_margin" type="float" setter="set_one_way_collision_margin" getter="get_one_way_collision_margin" default="1.0">
|
||||
The margin used for one-way collision (in pixels). Higher values will make the shape thicker, and work better for colliders that enter the shape at a high velocity.
|
||||
|
@ -14,6 +14,9 @@
|
||||
<member name="flat" type="bool" setter="set_flat" getter="is_flat" default="false">
|
||||
</member>
|
||||
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" />
|
||||
<member name="hide_slider" type="bool" setter="set_hide_slider" getter="is_hiding_slider" default="false">
|
||||
If [code]true[/code], the slider is hidden.
|
||||
</member>
|
||||
<member name="label" type="String" setter="set_label" getter="get_label" default="""">
|
||||
</member>
|
||||
<member name="read_only" type="bool" setter="set_read_only" getter="is_read_only" default="false">
|
||||
|
@ -20,6 +20,13 @@
|
||||
Creates the agent.
|
||||
</description>
|
||||
</method>
|
||||
<method name="agent_get_map" qualifiers="const">
|
||||
<return type="RID" />
|
||||
<argument index="0" name="agent" type="RID" />
|
||||
<description>
|
||||
Returns the navigation map [RID] the requested [code]agent[/code] is currently assigned to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="agent_is_map_changed" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="agent" type="RID" />
|
||||
@ -122,6 +129,13 @@
|
||||
Create a new map.
|
||||
</description>
|
||||
</method>
|
||||
<method name="map_get_agents" qualifiers="const">
|
||||
<return type="Array" />
|
||||
<argument index="0" name="map" type="RID" />
|
||||
<description>
|
||||
Returns all navigation agents [RID]s that are currently assigned to the requested navigation [code]map[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="map_get_cell_size" qualifiers="const">
|
||||
<return type="float" />
|
||||
<argument index="0" name="map" type="RID" />
|
||||
@ -162,6 +176,13 @@
|
||||
Returns the navigation path to reach the destination from the origin.
|
||||
</description>
|
||||
</method>
|
||||
<method name="map_get_regions" qualifiers="const">
|
||||
<return type="Array" />
|
||||
<argument index="0" name="map" type="RID" />
|
||||
<description>
|
||||
Returns all navigation regions [RID]s that are currently assigned to the requested navigation [code]map[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="map_is_active" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="nap" type="RID" />
|
||||
@ -199,6 +220,13 @@
|
||||
Creates a new region.
|
||||
</description>
|
||||
</method>
|
||||
<method name="region_get_map" qualifiers="const">
|
||||
<return type="RID" />
|
||||
<argument index="0" name="region" type="RID" />
|
||||
<description>
|
||||
Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="region_set_map" qualifiers="const">
|
||||
<return type="void" />
|
||||
<argument index="0" name="region" type="RID" />
|
||||
|
@ -1,10 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="NavigationMeshGenerator" inherits="Object" version="3.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
This class is responsible for creating and clearing navigation meshes.
|
||||
Helper class for creating and clearing navigation meshes.
|
||||
</brief_description>
|
||||
<description>
|
||||
This class is responsible for creating and clearing navigation meshes.
|
||||
This class is responsible for creating and clearing 3D navigation meshes used as [NavigationMesh] resources inside [NavigationMeshInstance]. The [NavigationMeshGenerator] has very limited to no use for 2D as the navigation mesh baking process expects 3D node types and 3D source geometry to parse.
|
||||
The entire navigation mesh baking is best done in a separate thread as the voxelization, collision tests and mesh optimization steps involved are very performance and time hungry operations.
|
||||
Navigation mesh baking happens in multiple steps and the result depends on 3D source geometry and properties of the [NavigationMesh] resource. In the first step, starting from a root node and depending on [NavigationMesh] properties all valid 3D source geometry nodes are collected from the [SceneTree]. Second, all collected nodes are parsed for their relevant 3D geometry data and a combined 3D mesh is build. Due to the many different types of parsable objects, from normal [MeshInstance]s to [CSGShape]s or various [CollisionObject]s, some operations to collect geometry data can trigger [VisualServer] and [PhysicsServer] synchronizations. Server synchronization can have a negative effect on baking time or framerate as it often involves [Mutex] locking for thread security. Many parsable objects and the continuous synchronization with other threaded Servers can increase the baking time significantly. On the other hand only a few but very large and complex objects will take some time to prepare for the Servers which can noticeably stall the next frame render. As a general rule the total amount of parsable objects and their individual size and complexity should be balanced to avoid framerate issues or very long baking times. The combined mesh is then passed to the Recast Navigation Object to test the source geometry for walkable terrain suitable to [NavigationMesh] agent properties by creating a voxel world around the meshes bounding area.
|
||||
The finalized navigation mesh is then returned and stored inside the [NavigationMesh] for use as a resource inside [NavigationMeshInstance] nodes.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
@ -14,14 +17,14 @@
|
||||
<argument index="0" name="nav_mesh" type="NavigationMesh" />
|
||||
<argument index="1" name="root_node" type="Node" />
|
||||
<description>
|
||||
Bakes the navigation mesh. This will allow you to use pathfinding with the navigation system.
|
||||
Bakes navigation data to the provided [code]nav_mesh[/code] by parsing child nodes under the provided [code]root_node[/code] or a specific group of nodes for potential source geometry. The parse behavior can be controlled with the [member NavigationMesh.geometry/parsed_geometry_type] and [member NavigationMesh.geometry/source_geometry_mode] properties on the [NavigationMesh] resource.
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear">
|
||||
<return type="void" />
|
||||
<argument index="0" name="nav_mesh" type="NavigationMesh" />
|
||||
<description>
|
||||
Clears the navigation mesh.
|
||||
Removes all polygons and vertices from the provided [code]nav_mesh[/code] resource.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
|
@ -13,7 +13,7 @@
|
||||
<return type="void" />
|
||||
<argument index="0" name="on_thread" type="bool" default="true" />
|
||||
<description>
|
||||
Bakes the [NavigationMesh]. If [code]on_thread[/code] is set to [code]true[/code] (default), the baking is done on a separate thread. Baking on separate thread is useful because navigation baking is not a cheap operation. When it is completed, it automatically sets the new [NavigationMesh]. Please note that baking on separate thread may be very slow if geometry is parsed from meshes as async access to each mesh involves heavy synchronization.
|
||||
Bakes the [NavigationMesh]. If [code]on_thread[/code] is set to [code]true[/code] (default), the baking is done on a separate thread. Baking on separate thread is useful because navigation baking is not a cheap operation. When it is completed, it automatically sets the new [NavigationMesh]. Please note that baking on separate thread may be very slow if geometry is parsed from meshes as async access to each mesh involves heavy synchronization. Also, please note that baking on a separate thread is automatically disabled on operating systems that cannot use threads (such as HTML5 with threads disabled).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_region_rid" qualifiers="const">
|
||||
|
@ -15,6 +15,12 @@
|
||||
Returns the [Navigation] node that the obstacle is using for its navigation system.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_rid" qualifiers="const">
|
||||
<return type="RID" />
|
||||
<description>
|
||||
Returns the [RID] of this obstacle on the [NavigationServer].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_navigation">
|
||||
<return type="void" />
|
||||
<argument index="0" name="navigation" type="Node" />
|
||||
|
@ -15,6 +15,12 @@
|
||||
Returns the [Navigation2D] node that the obstacle is using for its navigation system.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_rid" qualifiers="const">
|
||||
<return type="RID" />
|
||||
<description>
|
||||
Returns the [RID] of this obstacle on the [Navigation2DServer].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_navigation">
|
||||
<return type="void" />
|
||||
<argument index="0" name="navigation" type="Node" />
|
||||
|
@ -20,6 +20,13 @@
|
||||
Creates the agent.
|
||||
</description>
|
||||
</method>
|
||||
<method name="agent_get_map" qualifiers="const">
|
||||
<return type="RID" />
|
||||
<argument index="0" name="agent" type="RID" />
|
||||
<description>
|
||||
Returns the navigation map [RID] the requested [code]agent[/code] is currently assigned to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="agent_is_map_changed" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="agent" type="RID" />
|
||||
@ -122,6 +129,13 @@
|
||||
Create a new map.
|
||||
</description>
|
||||
</method>
|
||||
<method name="map_get_agents" qualifiers="const">
|
||||
<return type="Array" />
|
||||
<argument index="0" name="map" type="RID" />
|
||||
<description>
|
||||
Returns all navigation agents [RID]s that are currently assigned to the requested navigation [code]map[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="map_get_cell_height" qualifiers="const">
|
||||
<return type="float" />
|
||||
<argument index="0" name="map" type="RID" />
|
||||
@ -187,6 +201,13 @@
|
||||
Returns the navigation path to reach the destination from the origin.
|
||||
</description>
|
||||
</method>
|
||||
<method name="map_get_regions" qualifiers="const">
|
||||
<return type="Array" />
|
||||
<argument index="0" name="map" type="RID" />
|
||||
<description>
|
||||
Returns all navigation regions [RID]s that are currently assigned to the requested navigation [code]map[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="map_get_up" qualifiers="const">
|
||||
<return type="Vector3" />
|
||||
<argument index="0" name="map" type="RID" />
|
||||
@ -264,6 +285,13 @@
|
||||
Creates a new region.
|
||||
</description>
|
||||
</method>
|
||||
<method name="region_get_map" qualifiers="const">
|
||||
<return type="RID" />
|
||||
<argument index="0" name="region" type="RID" />
|
||||
<description>
|
||||
Returns the navigation map [RID] the requested [code]region[/code] is currently assigned to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="region_set_map" qualifiers="const">
|
||||
<return type="void" />
|
||||
<argument index="0" name="region" type="RID" />
|
||||
|
@ -26,7 +26,9 @@
|
||||
<argument index="1" name="with_shape" type="Shape2D" />
|
||||
<argument index="2" name="shape_xform" type="Transform2D" />
|
||||
<description>
|
||||
Returns a list of the points where this shape touches another. If there are no collisions the list is empty.
|
||||
Returns a list of contact point pairs where this shape touches another.
|
||||
If there are no collisions, the returned list is empty. Otherwise, the returned list contains contact points arranged in pairs, with entries alternating between points on the boundary of this shape and points on the boundary of [code]with_shape[/code].
|
||||
A collision pair A, B can be used to calculate the collision normal with [code](B - A).normalized()[/code], and the collision depth with [code](B - A).length()[/code]. This information is typically used to separate shapes, particularly in collision solvers.
|
||||
This method needs the transformation matrix for this shape ([code]local_xform[/code]), the shape to check collisions with ([code]with_shape[/code]), and the transformation matrix of that shape ([code]shape_xform[/code]).
|
||||
</description>
|
||||
</method>
|
||||
@ -50,7 +52,9 @@
|
||||
<argument index="3" name="shape_xform" type="Transform2D" />
|
||||
<argument index="4" name="shape_motion" type="Vector2" />
|
||||
<description>
|
||||
Returns a list of the points where this shape would touch another, if a given movement was applied. If there are no collisions the list is empty.
|
||||
Returns a list of contact point pairs where this shape would touch another, if a given movement was applied.
|
||||
If there would be no collisions, the returned list is empty. Otherwise, the returned list contains contact points arranged in pairs, with entries alternating between points on the boundary of this shape and points on the boundary of [code]with_shape[/code].
|
||||
A collision pair A, B can be used to calculate the collision normal with [code](B - A).normalized()[/code], and the collision depth with [code](B - A).length()[/code]. This information is typically used to separate shapes, particularly in collision solvers.
|
||||
This method needs the transformation matrix for this shape ([code]local_xform[/code]), the movement to test on this shape ([code]local_motion[/code]), the shape to check collisions with ([code]with_shape[/code]), the transformation matrix of that shape ([code]shape_xform[/code]), and the movement to test onto the other object ([code]shape_motion[/code]).
|
||||
</description>
|
||||
</method>
|
||||
|
@ -43,7 +43,7 @@
|
||||
Converts the given Unix timestamp to an ISO 8601 date string (YYYY-MM-DD).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_datetime_dict_from_string" qualifiers="const">
|
||||
<method name="get_datetime_dict_from_datetime_string" qualifiers="const">
|
||||
<return type="Dictionary" />
|
||||
<argument index="0" name="datetime" type="String" />
|
||||
<argument index="1" name="weekday" type="bool" />
|
||||
@ -68,7 +68,7 @@
|
||||
The returned Dictionary's values will be the same as the [method get_datetime_dict_from_system] if the Unix timestamp is the current time, with the exception of Daylight Savings Time as it cannot be determined from the epoch.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_datetime_string_from_dict" qualifiers="const">
|
||||
<method name="get_datetime_string_from_datetime_dict" qualifiers="const">
|
||||
<return type="String" />
|
||||
<argument index="0" name="datetime" type="Dictionary" />
|
||||
<argument index="1" name="use_space" type="bool" />
|
||||
|
@ -592,7 +592,8 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
|
||||
for value in e.values.values():
|
||||
f.write("- **{}** = **{}**".format(value.name, value.value))
|
||||
if value.text is not None and value.text.strip() != "":
|
||||
f.write(" --- " + rstize_text(value.text.strip(), state))
|
||||
# If value.text contains a bullet point list, each entry needs additional indentation
|
||||
f.write(" --- " + indent_bullets(rstize_text(value.text.strip(), state)))
|
||||
|
||||
f.write("\n\n")
|
||||
|
||||
@ -738,7 +739,7 @@ def rstize_text(text, state): # type: (str, State) -> str
|
||||
|
||||
pre_text = text[:pos]
|
||||
indent_level = 0
|
||||
while text[pos + 1] == "\t":
|
||||
while pos + 1 < len(text) and text[pos + 1] == "\t":
|
||||
pos += 1
|
||||
indent_level += 1
|
||||
post_text = text[pos + 1 :]
|
||||
@ -1190,5 +1191,24 @@ def make_link(url, title): # type: (str, str) -> str
|
||||
return "`" + url + " <" + url + ">`__"
|
||||
|
||||
|
||||
def indent_bullets(text): # type: (str) -> str
|
||||
# Take the text and check each line for a bullet point represented by "-".
|
||||
# Where found, indent the given line by a further "\t".
|
||||
# Used to properly indent bullet points contained in the description for enum values.
|
||||
# Ignore the first line - text will be prepended to it so bullet points wouldn't work anyway.
|
||||
bullet_points = "-"
|
||||
|
||||
lines = text.splitlines(keepends=True)
|
||||
for line_index, line in enumerate(lines[1:], start=1):
|
||||
pos = 0
|
||||
while pos < len(line) and line[pos] == "\t":
|
||||
pos += 1
|
||||
|
||||
if pos < len(line) and line[pos] in bullet_points:
|
||||
lines[line_index] = line[:pos] + "\t" + line[pos:]
|
||||
|
||||
return "".join(lines)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -3228,7 +3228,7 @@ Ref<Animation> AnimationTrackEditor::get_current_animation() const {
|
||||
return animation;
|
||||
}
|
||||
|
||||
void AnimationTrackEditor::_root_removed(Node *p_root) {
|
||||
void AnimationTrackEditor::_root_removed() {
|
||||
root = nullptr;
|
||||
}
|
||||
|
||||
|
@ -376,7 +376,7 @@ class AnimationTrackEditor : public VBoxContainer {
|
||||
TrackIndices _confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_create_reset, Ref<Animation> p_reset_anim, bool p_create_beziers);
|
||||
void _insert_delay(bool p_create_reset, bool p_create_beziers);
|
||||
|
||||
void _root_removed(Node *p_root);
|
||||
void _root_removed();
|
||||
|
||||
PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val = nullptr);
|
||||
|
||||
|
@ -562,6 +562,9 @@ void EditorSpinSlider::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_flat", "flat"), &EditorSpinSlider::set_flat);
|
||||
ClassDB::bind_method(D_METHOD("is_flat"), &EditorSpinSlider::is_flat);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_hide_slider", "hide_slider"), &EditorSpinSlider::set_hide_slider);
|
||||
ClassDB::bind_method(D_METHOD("is_hiding_slider"), &EditorSpinSlider::is_hiding_slider);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_gui_input"), &EditorSpinSlider::_gui_input);
|
||||
ClassDB::bind_method(D_METHOD("_value_input_gui_input", "event"), &EditorSpinSlider::_value_input_gui_input);
|
||||
ClassDB::bind_method(D_METHOD("_grabber_mouse_entered"), &EditorSpinSlider::_grabber_mouse_entered);
|
||||
@ -574,6 +577,7 @@ void EditorSpinSlider::_bind_methods() {
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "label"), "set_label", "get_label");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "read_only"), "set_read_only", "is_read_only");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_slider"), "set_hide_slider", "is_hiding_slider");
|
||||
}
|
||||
|
||||
EditorSpinSlider::EditorSpinSlider() {
|
||||
|
@ -2852,11 +2852,13 @@ void ThemeTypeEditor::_update_stylebox_from_leading() {
|
||||
edited_theme->get_stylebox_list(edited_type, &names);
|
||||
List<Ref<StyleBox>> styleboxes;
|
||||
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
|
||||
if (E->get() == leading_stylebox.item_name) {
|
||||
Ref<StyleBox> sb = edited_theme->get_stylebox(E->get(), edited_type);
|
||||
|
||||
// Avoid itself, stylebox can be shared between items.
|
||||
if (sb == leading_stylebox.stylebox) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Ref<StyleBox> sb = edited_theme->get_stylebox(E->get(), edited_type);
|
||||
if (sb->get_class() == leading_stylebox.stylebox->get_class()) {
|
||||
styleboxes.push_back(sb);
|
||||
}
|
||||
|
@ -1082,19 +1082,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
||||
// Assigning here, to be sure that it appears in docs
|
||||
GLOBAL_DEF("rendering/2d/options/use_nvidia_rect_flicker_workaround", false);
|
||||
|
||||
GLOBAL_DEF("display/window/size/width", 1024);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/width", PropertyInfo(Variant::INT, "display/window/size/width", PROPERTY_HINT_RANGE, "0,7680,1,or_greater")); // 8K resolution
|
||||
GLOBAL_DEF("display/window/size/height", 600);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/height", PropertyInfo(Variant::INT, "display/window/size/height", PROPERTY_HINT_RANGE, "0,4320,1,or_greater")); // 8K resolution
|
||||
GLOBAL_DEF("display/window/size/resizable", true);
|
||||
GLOBAL_DEF("display/window/size/borderless", false);
|
||||
GLOBAL_DEF("display/window/size/fullscreen", false);
|
||||
GLOBAL_DEF("display/window/size/always_on_top", false);
|
||||
GLOBAL_DEF("display/window/size/test_width", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_width", PropertyInfo(Variant::INT, "display/window/size/test_width", PROPERTY_HINT_RANGE, "0,7680,1,or_greater")); // 8K resolution
|
||||
GLOBAL_DEF("display/window/size/test_height", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_height", PropertyInfo(Variant::INT, "display/window/size/test_height", PROPERTY_HINT_RANGE, "0,4320,1,or_greater")); // 8K resolution
|
||||
|
||||
if (use_custom_res) {
|
||||
if (!force_res) {
|
||||
video_mode.width = GLOBAL_GET("display/window/size/width");
|
||||
|
53
misc/dist/html/editor.html
vendored
53
misc/dist/html/editor.html
vendored
@ -68,6 +68,11 @@
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: hsla(0, 0%, 0%, 0.5);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.welcome-modal-title {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.welcome-modal-content {
|
||||
@ -238,7 +243,7 @@
|
||||
onclick="if (event.target === this) closeWelcomeModal(false)"
|
||||
>
|
||||
<div class="welcome-modal-content">
|
||||
<h2 id="welcome-modal-title">Important - Please read before continuing</h2>
|
||||
<h2 id="welcome-modal-title" class="welcome-modal-title">Important - Please read before continuing</h2>
|
||||
<div id="welcome-modal-description">
|
||||
<p>
|
||||
The Godot Web Editor has some limitations compared to the native version.
|
||||
@ -254,9 +259,38 @@
|
||||
>Web editor documentation</a> for usage instructions and limitations.
|
||||
</p>
|
||||
</div>
|
||||
<button id="welcome-modal-dismiss" class="btn" type="button" onclick="closeWelcomeModal(true)" style="margin-top: 1rem">
|
||||
OK, don't show again
|
||||
</button>
|
||||
<div id="welcome-modal-description-no-cross-origin-isolation" style="display: none">
|
||||
<p>
|
||||
The web server does not support cross-origin isolation,
|
||||
which is required for the Godot Web Editor to function.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Reasons for cross-origin isolation being disabled:</strong>
|
||||
<ul>
|
||||
<li id="welcome-modal-reason-not-secure">
|
||||
This page is not served from a secure context (HTTPS <i>or</i> localhost).
|
||||
</li>
|
||||
<li>
|
||||
This page may not be served with cross-origin isolation headers
|
||||
(check with the developer tools' Network tab).
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
If you are self-hosting the web editor,
|
||||
refer to
|
||||
<a
|
||||
href="https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_web.html#threads"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Exporting for the Web - Threads</a> for more information.
|
||||
</p>
|
||||
</div>
|
||||
<div style="text-align: center">
|
||||
<button id="welcome-modal-dismiss" class="btn" type="button" onclick="closeWelcomeModal(true)" style="margin-top: 1rem">
|
||||
OK, don't show again
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="tabs-buttons">
|
||||
@ -361,7 +395,16 @@
|
||||
});
|
||||
}
|
||||
|
||||
if (localStorage.getItem("welcomeModalDismissed") !== 'true') {
|
||||
if (!crossOriginIsolated) {
|
||||
// Display error dialog as threading support is required for the editor.
|
||||
setButtonEnabled('startButton', false);
|
||||
document.getElementById("welcome-modal-description").style.display = "none";
|
||||
document.getElementById("welcome-modal-description-no-cross-origin-isolation").style.display = "block";
|
||||
document.getElementById("welcome-modal-dismiss").style.display = "none";
|
||||
document.getElementById("welcome-modal-reason-not-secure").style.display = window.isSecureContext ? "none" : "list-item";
|
||||
}
|
||||
|
||||
if (!crossOriginIsolated || localStorage.getItem("welcomeModalDismissed") !== 'true') {
|
||||
document.getElementById("welcome-modal").style.display = "block";
|
||||
document.getElementById("welcome-modal-dismiss").focus();
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
[Desktop Entry]
|
||||
Name=Godot Engine
|
||||
GenericName=Libre game engine
|
||||
GenericName[el]=Ελεύθερη μηχανή παιχνιδιού
|
||||
GenericName[fr]=Moteur de jeu libre
|
||||
GenericName[zh_CN]=自由的游戏引擎
|
||||
Comment=Multi-platform 2D and 3D game engine with a feature-rich editor
|
||||
Comment[el]=2D και 3D μηχανή παιχνιδιού πολλαπλών πλατφορμών με επεξεργαστή πλούσιο σε χαρακτηριστικά
|
||||
Comment[fr]=Moteur de jeu 2D et 3D multiplateforme avec un éditeur riche en fonctionnalités
|
||||
Comment[zh_CN]=多平台 2D 和 3D 游戏引擎,带有功能丰富的编辑器
|
||||
Exec=godot %f
|
||||
Icon=godot
|
||||
|
@ -1387,13 +1387,13 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face
|
||||
}
|
||||
|
||||
// Ensure B has points either side of or in the plane of A.
|
||||
int in_plane_count = 0, over_count = 0, under_count = 0;
|
||||
int over_count = 0, under_count = 0;
|
||||
Plane plane_a(vertices_a[0], vertices_a[1], vertices_a[2]);
|
||||
ERR_FAIL_COND_MSG(plane_a.normal == Vector3(), "Couldn't form plane from Brush A face.");
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (plane_a.has_point(vertices_b[i])) {
|
||||
in_plane_count++;
|
||||
// In plane.
|
||||
} else if (plane_a.is_point_over(vertices_b[i])) {
|
||||
over_count++;
|
||||
} else {
|
||||
@ -1406,7 +1406,6 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face
|
||||
}
|
||||
|
||||
// Ensure A has points either side of or in the plane of B.
|
||||
in_plane_count = 0;
|
||||
over_count = 0;
|
||||
under_count = 0;
|
||||
Plane plane_b(vertices_b[0], vertices_b[1], vertices_b[2]);
|
||||
@ -1414,7 +1413,7 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (plane_b.has_point(vertices_a[i])) {
|
||||
in_plane_count++;
|
||||
// In plane.
|
||||
} else if (plane_b.is_point_over(vertices_a[i])) {
|
||||
over_count++;
|
||||
} else {
|
||||
|
@ -852,26 +852,24 @@
|
||||
<method name="range" qualifiers="vararg">
|
||||
<return type="Array" />
|
||||
<description>
|
||||
Returns an array with the given range. Range can be 1 argument [code]N[/code] (0 to [code]N[/code] - 1), two arguments ([code]initial[/code], [code]final - 1[/code]) or three arguments ([code]initial[/code], [code]final - 1[/code], [code]increment[/code]). Returns an empty array if the range isn't valid (e.g. [code]range(2, 5, -1)[/code] or [code]range(5, 5, 1)[/code]).
|
||||
Returns an array with the given range. [code]range()[/code] can have 1 argument N ([code]0[/code] to [code]N - 1[/code]), two arguments ([code]initial[/code], [code]final - 1[/code]) or three arguments ([code]initial[/code], [code]final - 1[/code], [code]increment[/code]). [code]increment[/code] can be negative. If [code]increment[/code] is negative, [code]final - 1[/code] will become [code]final + 1[/code]. Also, the initial value must be greater than the final value for the loop to run.
|
||||
Returns an array with the given range. [method range] can be called in three ways:
|
||||
[code]range(n: int)[/code]: Starts from 0, increases by steps of 1, and stops [i]before[/i] [code]n[/code]. The argument [code]n[/code] is [b]exclusive[/b].
|
||||
[code]range(b: int, n: int)[/code]: Starts from [code]b[/code], increases by steps of 1, and stops [i]before[/i] [code]n[/code]. The arguments [code]b[/code] and [code]n[/code] are [b]inclusive[/b] and [b]exclusive[/b], respectively.
|
||||
[code]range(b: int, n: int, s: int)[/code]: Starts from [code]b[/code], increases/decreases by steps of [code]s[/code], and stops [i]before[/i] [code]n[/code]. The arguments [code]b[/code] and [code]n[/code] are [b]inclusive[/b] and [b]exclusive[/b], respectively. The argument [code]s[/code] [b]can[/b] be negative, but not [code]0[/code]. If [code]s[/code] is [code]0[/code], an error message is printed.
|
||||
[method range] converts all arguments to [int] before processing.
|
||||
[b]Note:[/b] Returns an empty array if no value meets the value constraint (e.g. [code]range(2, 5, -1)[/code] or [code]range(5, 5, 1)[/code]).
|
||||
Examples:
|
||||
[codeblock]
|
||||
print(range(4))
|
||||
print(range(2, 5))
|
||||
print(range(0, 6, 2))
|
||||
[/codeblock]
|
||||
Output:
|
||||
[codeblock]
|
||||
[0, 1, 2, 3]
|
||||
[2, 3, 4]
|
||||
[0, 2, 4]
|
||||
print(range(4)) # Prints [0, 1, 2, 3]
|
||||
print(range(2, 5)) # Prints [2, 3, 4]
|
||||
print(range(0, 6, 2)) # Prints [0, 2, 4]
|
||||
print(range(4, 1, -1)) # Prints [4, 3, 2]
|
||||
[/codeblock]
|
||||
To iterate over an [Array] backwards, use:
|
||||
[codeblock]
|
||||
var array = [3, 6, 9]
|
||||
var i := array.size() - 1
|
||||
while i >= 0:
|
||||
print(array[i])
|
||||
i -= 1
|
||||
for i in range(array.size(), 0, -1):
|
||||
print(array[i - 1])
|
||||
[/codeblock]
|
||||
Output:
|
||||
[codeblock]
|
||||
|
@ -1316,7 +1316,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
|
||||
|
||||
Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::BlockNode *p_block, int p_stack_level, int p_break_addr, int p_continue_addr) {
|
||||
codegen.push_stack_identifiers();
|
||||
int new_identifiers = 0;
|
||||
codegen.current_line = p_block->line;
|
||||
|
||||
for (int i = 0; i < p_block->statements.size(); i++) {
|
||||
@ -1347,7 +1346,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
|
||||
// copied because there is no _parse_statement :(
|
||||
codegen.add_stack_identifier(id->name, p_stack_level++);
|
||||
codegen.alloc_stack(p_stack_level);
|
||||
new_identifiers++;
|
||||
|
||||
GDScriptParser::OperatorNode *op = memnew(GDScriptParser::OperatorNode);
|
||||
op->op = GDScriptParser::OperatorNode::OP_ASSIGN;
|
||||
@ -1605,8 +1603,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
|
||||
|
||||
codegen.add_stack_identifier(lv->name, p_stack_level++);
|
||||
codegen.alloc_stack(p_stack_level);
|
||||
new_identifiers++;
|
||||
|
||||
} break;
|
||||
default: {
|
||||
//expression
|
||||
|
@ -938,6 +938,7 @@ void GridMapEditor::edit(GridMap *p_gridmap) {
|
||||
}
|
||||
|
||||
update_palette();
|
||||
_update_cursor_instance();
|
||||
|
||||
set_process(true);
|
||||
|
||||
|
@ -63,6 +63,7 @@ namespace GodotTools.Build
|
||||
startInfo.RedirectStandardOutput = true;
|
||||
startInfo.RedirectStandardError = true;
|
||||
startInfo.UseShellExecute = false;
|
||||
startInfo.CreateNoWindow = true;
|
||||
|
||||
if (UsingMonoMsBuildOnWindows)
|
||||
{
|
||||
|
@ -174,7 +174,8 @@ namespace GodotTools.Utils
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (Process process = Process.Start(startInfo))
|
||||
|
@ -250,6 +250,38 @@ RID GodotNavigationServer::map_get_closest_point_owner(RID p_map, const Vector3
|
||||
return map->get_closest_point_owner(p_point);
|
||||
}
|
||||
|
||||
Array GodotNavigationServer::map_get_regions(RID p_map) const {
|
||||
Array regions_rids;
|
||||
const NavMap *map = map_owner.getornull(p_map);
|
||||
ERR_FAIL_COND_V(map == nullptr, regions_rids);
|
||||
for (NavRegion *region : map->get_regions()) {
|
||||
regions_rids.push_back(region->get_self());
|
||||
}
|
||||
return regions_rids;
|
||||
}
|
||||
|
||||
Array GodotNavigationServer::map_get_agents(RID p_map) const {
|
||||
Array agents_rids;
|
||||
const NavMap *map = map_owner.getornull(p_map);
|
||||
ERR_FAIL_COND_V(map == nullptr, agents_rids);
|
||||
for (RvoAgent *agent : map->get_agents()) {
|
||||
agents_rids.push_back(agent->get_self());
|
||||
}
|
||||
return agents_rids;
|
||||
}
|
||||
|
||||
RID GodotNavigationServer::region_get_map(RID p_region) const {
|
||||
NavRegion *region = region_owner.getornull(p_region);
|
||||
ERR_FAIL_COND_V(region == nullptr, RID());
|
||||
return region->get_map()->get_self();
|
||||
}
|
||||
|
||||
RID GodotNavigationServer::agent_get_map(RID p_agent) const {
|
||||
RvoAgent *agent = agent_owner.getornull(p_agent);
|
||||
ERR_FAIL_COND_V(agent == nullptr, RID());
|
||||
return agent->get_map()->get_self();
|
||||
}
|
||||
|
||||
RID GodotNavigationServer::region_create() const {
|
||||
auto mut_this = const_cast<GodotNavigationServer *>(this);
|
||||
MutexLock lock(mut_this->operations_mutex);
|
||||
|
@ -108,14 +108,19 @@ public:
|
||||
virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const;
|
||||
virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const;
|
||||
|
||||
virtual Array map_get_regions(RID p_map) const;
|
||||
virtual Array map_get_agents(RID p_map) const;
|
||||
|
||||
virtual RID region_create() const;
|
||||
COMMAND_2(region_set_map, RID, p_region, RID, p_map);
|
||||
virtual RID region_get_map(RID p_region) const;
|
||||
COMMAND_2(region_set_transform, RID, p_region, Transform, p_transform);
|
||||
COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh);
|
||||
virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const;
|
||||
|
||||
virtual RID agent_create() const;
|
||||
COMMAND_2(agent_set_map, RID, p_agent, RID, p_map);
|
||||
virtual RID agent_get_map(RID p_agent) const;
|
||||
COMMAND_2(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist);
|
||||
COMMAND_2(agent_set_max_neighbors, RID, p_agent, int, p_count);
|
||||
COMMAND_2(agent_set_time_horizon, RID, p_agent, real_t, p_time);
|
||||
|
@ -447,7 +447,7 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
|
||||
cfg.minRegionArea = (int)(p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size());
|
||||
cfg.mergeRegionArea = (int)(p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size());
|
||||
cfg.maxVertsPerPoly = (int)p_nav_mesh->get_verts_per_poly();
|
||||
cfg.detailSampleDist = p_nav_mesh->get_detail_sample_distance() < 0.9f ? 0 : p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance();
|
||||
cfg.detailSampleDist = MAX(p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance(), 0.1f);
|
||||
cfg.detailSampleMaxError = p_nav_mesh->get_cell_height() * p_nav_mesh->get_detail_sample_max_error();
|
||||
|
||||
cfg.bmin[0] = bmin[0];
|
||||
@ -463,6 +463,14 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
|
||||
#endif
|
||||
rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height);
|
||||
|
||||
// ~30000000 seems to be around sweetspot where Editor baking breaks
|
||||
if ((cfg.width * cfg.height) > 30000000) {
|
||||
WARN_PRINT("NavigationMesh baking process will likely fail."
|
||||
"\nSource geometry is suspiciously big for the current Cell Size and Cell Height in the NavMesh Resource bake settings."
|
||||
"\nIf baking does not fail, the resulting NavigationMesh will create serious pathfinding performance issues."
|
||||
"\nIt is advised to increase Cell Size and/or Cell Height in the NavMesh Resource bake settings or reduce the size / scale of the source geometry.");
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (ep)
|
||||
ep->step(TTR("Creating heightfield..."), 3);
|
||||
|
@ -193,8 +193,11 @@ def configure(env):
|
||||
|
||||
if env["target"].startswith("release"):
|
||||
if env["optimize"] == "speed": # optimize for speed (default)
|
||||
env.Append(LINKFLAGS=["-O2"])
|
||||
env.Append(CCFLAGS=["-O2", "-fomit-frame-pointer"])
|
||||
# `-O2` is more friendly to debuggers than `-O3`, leading to better crash backtraces
|
||||
# when using `target=release_debug`.
|
||||
opt = "-O3" if env["target"] == "release" else "-O2"
|
||||
env.Append(LINKFLAGS=[opt])
|
||||
env.Append(CCFLAGS=[opt, "-fomit-frame-pointer"])
|
||||
elif env["optimize"] == "size": # optimize for size
|
||||
env.Append(CCFLAGS=["-Os"])
|
||||
env.Append(LINKFLAGS=["-Os"])
|
||||
|
@ -51,8 +51,11 @@ def configure(env):
|
||||
if env["target"].startswith("release"):
|
||||
env.Append(CPPDEFINES=["NDEBUG", ("NS_BLOCK_ASSERTIONS", 1)])
|
||||
if env["optimize"] == "speed": # optimize for speed (default)
|
||||
env.Append(CCFLAGS=["-O2", "-ftree-vectorize", "-fomit-frame-pointer"])
|
||||
env.Append(LINKFLAGS=["-O2"])
|
||||
# `-O2` is more friendly to debuggers than `-O3`, leading to better crash backtraces
|
||||
# when using `target=release_debug`.
|
||||
opt = "-O3" if env["target"] == "release" else "-O2"
|
||||
env.Append(CCFLAGS=[opt, "-ftree-vectorize", "-fomit-frame-pointer"])
|
||||
env.Append(LINKFLAGS=[opt])
|
||||
elif env["optimize"] == "size": # optimize for size
|
||||
env.Append(CCFLAGS=["-Os", "-ftree-vectorize"])
|
||||
env.Append(LINKFLAGS=["-Os"])
|
||||
|
@ -2312,6 +2312,10 @@ void OS_Windows::_update_window_style(bool p_repaint, bool p_maximized) {
|
||||
}
|
||||
}
|
||||
|
||||
if (icon.is_valid()) {
|
||||
set_icon(icon);
|
||||
}
|
||||
|
||||
SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
|
||||
|
||||
if (p_repaint) {
|
||||
@ -2799,6 +2803,31 @@ String OS_Windows::_quote_command_line_argument(const String &p_text) const {
|
||||
return p_text;
|
||||
}
|
||||
|
||||
static void _append_to_pipe(char *p_bytes, int p_size, String *r_pipe, Mutex *p_pipe_mutex) {
|
||||
// Try to convert from default ANSI code page to Unicode.
|
||||
LocalVector<wchar_t> wchars;
|
||||
int total_wchars = MultiByteToWideChar(CP_ACP, 0, p_bytes, p_size, nullptr, 0);
|
||||
if (total_wchars > 0) {
|
||||
wchars.resize(total_wchars);
|
||||
if (MultiByteToWideChar(CP_ACP, 0, p_bytes, p_size, wchars.ptr(), total_wchars) == 0) {
|
||||
wchars.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (p_pipe_mutex) {
|
||||
p_pipe_mutex->lock();
|
||||
}
|
||||
if (wchars.empty()) {
|
||||
// Let's hope it's compatible with UTF-8.
|
||||
(*r_pipe) += String::utf8(p_bytes, p_size);
|
||||
} else {
|
||||
(*r_pipe) += String(wchars.ptr(), total_wchars);
|
||||
}
|
||||
if (p_pipe_mutex) {
|
||||
p_pipe_mutex->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
|
||||
String path = p_path.replace("/", "\\");
|
||||
|
||||
@ -2857,21 +2886,44 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
|
||||
if (p_blocking) {
|
||||
if (r_pipe) {
|
||||
CloseHandle(pipe[1]); // Close pipe write handle (only child process is writing).
|
||||
char buf[4096];
|
||||
|
||||
LocalVector<char> bytes;
|
||||
int bytes_in_buffer = 0;
|
||||
|
||||
const int CHUNK_SIZE = 4096;
|
||||
DWORD read = 0;
|
||||
for (;;) { // Read StdOut and StdErr from pipe.
|
||||
bool success = ReadFile(pipe[0], buf, 4096, &read, NULL);
|
||||
bytes.resize(bytes_in_buffer + CHUNK_SIZE);
|
||||
const bool success = ReadFile(pipe[0], bytes.ptr() + bytes_in_buffer, CHUNK_SIZE, &read, NULL);
|
||||
if (!success || read == 0) {
|
||||
break;
|
||||
}
|
||||
if (p_pipe_mutex) {
|
||||
p_pipe_mutex->lock();
|
||||
// Assume that all possible encodings are ASCII-compatible.
|
||||
// Break at newline to allow receiving long output in portions.
|
||||
int newline_index = -1;
|
||||
for (int i = read - 1; i >= 0; i--) {
|
||||
if (bytes[bytes_in_buffer + i] == '\n') {
|
||||
newline_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
(*r_pipe) += String::utf8(buf, read);
|
||||
if (p_pipe_mutex) {
|
||||
p_pipe_mutex->unlock();
|
||||
|
||||
if (newline_index == -1) {
|
||||
bytes_in_buffer += read;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
const int bytes_to_convert = bytes_in_buffer + (newline_index + 1);
|
||||
_append_to_pipe(bytes.ptr(), bytes_to_convert, r_pipe, p_pipe_mutex);
|
||||
|
||||
bytes_in_buffer = read - (newline_index + 1);
|
||||
memmove(bytes.ptr(), bytes.ptr() + bytes_to_convert, bytes_in_buffer);
|
||||
}
|
||||
|
||||
if (bytes_in_buffer > 0) {
|
||||
_append_to_pipe(bytes.ptr(), bytes_in_buffer, r_pipe, p_pipe_mutex);
|
||||
}
|
||||
|
||||
CloseHandle(pipe[0]); // Close pipe read handle.
|
||||
} else {
|
||||
WaitForSingleObject(pi.pi.hProcess, INFINITE);
|
||||
@ -2893,7 +2945,7 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
|
||||
process_map->insert(pid, pi);
|
||||
}
|
||||
return OK;
|
||||
};
|
||||
}
|
||||
|
||||
Error OS_Windows::kill(const ProcessID &p_pid) {
|
||||
ERR_FAIL_COND_V(!process_map->has(p_pid), FAILED);
|
||||
@ -3040,9 +3092,12 @@ void OS_Windows::set_native_icon(const String &p_filename) {
|
||||
|
||||
void OS_Windows::set_icon(const Ref<Image> &p_icon) {
|
||||
ERR_FAIL_COND(!p_icon.is_valid());
|
||||
Ref<Image> icon = p_icon->duplicate();
|
||||
if (icon->get_format() != Image::FORMAT_RGBA8)
|
||||
icon->convert(Image::FORMAT_RGBA8);
|
||||
if (icon != p_icon) {
|
||||
icon = p_icon->duplicate();
|
||||
if (icon->get_format() != Image::FORMAT_RGBA8) {
|
||||
icon->convert(Image::FORMAT_RGBA8);
|
||||
}
|
||||
}
|
||||
int w = icon->get_width();
|
||||
int h = icon->get_height();
|
||||
|
||||
|
@ -318,6 +318,8 @@ class OS_Windows : public OS {
|
||||
|
||||
uint32_t move_timer_id;
|
||||
|
||||
Ref<Image> icon;
|
||||
|
||||
HCURSOR hCursor;
|
||||
|
||||
Size2 min_size;
|
||||
|
@ -599,6 +599,7 @@ void AnimatedSprite::play(const StringName &p_animation, const bool p_backwards)
|
||||
}
|
||||
}
|
||||
|
||||
is_over = false;
|
||||
set_playing(true);
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "collision_object_2d.h"
|
||||
#include "core/engine.h"
|
||||
#include "scene/2d/area_2d.h"
|
||||
#include "scene/resources/concave_polygon_shape_2d.h"
|
||||
#include "scene/resources/convex_polygon_shape_2d.h"
|
||||
|
||||
@ -273,6 +274,9 @@ String CollisionPolygon2D::get_configuration_warning() const {
|
||||
warning += TTR("Invalid polygon. At least 2 points are needed in 'Segments' build mode.");
|
||||
}
|
||||
}
|
||||
if (one_way_collision && Object::cast_to<Area2D>(get_parent())) {
|
||||
warning += TTR("The One Way Collision property will be ignored when the parent is an Area2D.");
|
||||
}
|
||||
|
||||
return warning;
|
||||
}
|
||||
@ -295,6 +299,7 @@ void CollisionPolygon2D::set_one_way_collision(bool p_enable) {
|
||||
if (parent) {
|
||||
parent->shape_owner_set_one_way_collision(owner_id, p_enable);
|
||||
}
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
bool CollisionPolygon2D::is_one_way_collision_enabled() const {
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "collision_object_2d.h"
|
||||
#include "core/engine.h"
|
||||
#include "scene/2d/area_2d.h"
|
||||
#include "scene/resources/capsule_shape_2d.h"
|
||||
#include "scene/resources/circle_shape_2d.h"
|
||||
#include "scene/resources/concave_polygon_shape_2d.h"
|
||||
@ -204,6 +205,9 @@ String CollisionShape2D::get_configuration_warning() const {
|
||||
warning += TTR("Polygon-based shapes are not meant be used nor edited directly through the CollisionShape2D node. Please use the CollisionPolygon2D node instead.");
|
||||
}
|
||||
}
|
||||
if (one_way_collision && Object::cast_to<Area2D>(get_parent())) {
|
||||
warning += TTR("The One Way Collision property will be ignored when the parent is an Area2D.");
|
||||
}
|
||||
|
||||
return warning;
|
||||
}
|
||||
@ -226,6 +230,7 @@ void CollisionShape2D::set_one_way_collision(bool p_enable) {
|
||||
if (parent) {
|
||||
parent->shape_owner_set_one_way_collision(owner_id, p_enable);
|
||||
}
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
bool CollisionShape2D::is_one_way_collision_enabled() const {
|
||||
|
@ -36,8 +36,11 @@
|
||||
#include "servers/navigation_2d_server.h"
|
||||
|
||||
void NavigationObstacle2D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_rid"), &NavigationObstacle2D::get_rid);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle2D::set_navigation_node);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle2D::get_navigation_node);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_estimate_radius", "estimate_radius"), &NavigationObstacle2D::set_estimate_radius);
|
||||
ClassDB::bind_method(D_METHOD("is_radius_estimated"), &NavigationObstacle2D::is_radius_estimated);
|
||||
ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationObstacle2D::set_radius);
|
||||
@ -92,7 +95,7 @@ void NavigationObstacle2D::_notification(int p_what) {
|
||||
parent_node2d = nullptr;
|
||||
} break;
|
||||
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||
if (parent_node2d) {
|
||||
if (parent_node2d && parent_node2d->is_inside_tree()) {
|
||||
Navigation2DServer::get_singleton()->agent_set_position(agent, parent_node2d->get_global_transform().get_origin());
|
||||
}
|
||||
|
||||
@ -136,6 +139,11 @@ String NavigationObstacle2D::get_configuration_warning() const {
|
||||
return TTR("The NavigationObstacle2D only serves to provide collision avoidance to a Node2D object.");
|
||||
}
|
||||
|
||||
if (Object::cast_to<StaticBody2D>(get_parent())) {
|
||||
return TTR("The NavigationObstacle2D is intended for constantly moving bodies like KinematicBody2D or RigidBody2D as it creates only an RVO avoidance radius and does not follow scene geometry exactly."
|
||||
"\nNot constantly moving or complete static objects should be captured with a refreshed NavigationPolygon so agents can not only avoid them but also move along those objects outline at high detail");
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
@ -155,13 +163,13 @@ void NavigationObstacle2D::reevaluate_agent_radius() {
|
||||
}
|
||||
|
||||
real_t NavigationObstacle2D::estimate_agent_radius() const {
|
||||
if (parent_node2d) {
|
||||
if (parent_node2d && parent_node2d->is_inside_tree()) {
|
||||
// Estimate the radius of this physics body
|
||||
real_t radius = 0.0;
|
||||
for (int i(0); i < parent_node2d->get_child_count(); i++) {
|
||||
// For each collision shape
|
||||
CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(parent_node2d->get_child(i));
|
||||
if (cs) {
|
||||
if (cs && cs->is_inside_tree()) {
|
||||
// Take the distance between the Body center to the shape center
|
||||
real_t r = cs->get_transform().get_origin().length();
|
||||
if (cs->get_shape().is_valid()) {
|
||||
@ -172,6 +180,9 @@ real_t NavigationObstacle2D::estimate_agent_radius() const {
|
||||
r *= MAX(s.x, s.y);
|
||||
// Takes the biggest radius
|
||||
radius = MAX(radius, r);
|
||||
} else if (cs && !cs->is_inside_tree()) {
|
||||
WARN_PRINT("A CollisionShape2D of the NavigationObstacle2D parent node was not inside the SceneTree when estimating the obstacle radius."
|
||||
"\nMove the NavigationObstacle2D to a child position below any CollisionShape2D node of the parent node so the CollisionShape2D is already inside the SceneTree.");
|
||||
}
|
||||
}
|
||||
Vector2 s = parent_node2d->get_global_transform().get_scale();
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "navigation_mesh_instance.h"
|
||||
|
||||
#include "core/os/os.h"
|
||||
#include "core/os/thread.h"
|
||||
#include "mesh_instance.h"
|
||||
#include "navigation.h"
|
||||
@ -178,7 +179,12 @@ void NavigationMeshInstance::bake_navigation_mesh(bool p_on_thread) {
|
||||
BakeThreadsArgs *args = memnew(BakeThreadsArgs);
|
||||
args->nav_region = this;
|
||||
|
||||
if (p_on_thread) {
|
||||
if (p_on_thread && !OS::get_singleton()->can_use_threads()) {
|
||||
WARN_PRINT("NavigationMesh bake 'on_thread' will be disabled as the current OS does not support multiple threads."
|
||||
"\nAs a fallback the navigation mesh will bake on the main thread which can cause framerate issues.");
|
||||
}
|
||||
|
||||
if (p_on_thread && OS::get_singleton()->can_use_threads()) {
|
||||
bake_thread.start(_bake_navigation_mesh, args);
|
||||
} else {
|
||||
_bake_navigation_mesh(args);
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include "servers/navigation_server.h"
|
||||
|
||||
void NavigationObstacle::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_rid"), &NavigationObstacle::get_rid);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle::set_navigation_node);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle::get_navigation_node);
|
||||
ClassDB::bind_method(D_METHOD("is_radius_estimated"), &NavigationObstacle::is_radius_estimated);
|
||||
@ -92,7 +94,7 @@ void NavigationObstacle::_notification(int p_what) {
|
||||
parent_spatial = nullptr;
|
||||
} break;
|
||||
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||
if (parent_spatial) {
|
||||
if (parent_spatial && parent_spatial->is_inside_tree()) {
|
||||
NavigationServer::get_singleton()->agent_set_position(agent, parent_spatial->get_global_transform().origin);
|
||||
}
|
||||
|
||||
@ -140,7 +142,12 @@ Node *NavigationObstacle::get_navigation_node() const {
|
||||
|
||||
String NavigationObstacle::get_configuration_warning() const {
|
||||
if (!Object::cast_to<Spatial>(get_parent())) {
|
||||
return TTR("The NavigationObstacle only serves to provide collision avoidance to a spatial object.");
|
||||
return TTR("The NavigationObstacle only serves to provide collision avoidance to a Spatial inheriting parent object.");
|
||||
}
|
||||
|
||||
if (Object::cast_to<StaticBody>(get_parent())) {
|
||||
return TTR("The NavigationObstacle is intended for constantly moving bodies like KinematicBody3D or RigidBody3D as it creates only an RVO avoidance radius and does not follow scene geometry exactly."
|
||||
"\nNot constantly moving or complete static objects should be (re)baked to a NavigationMesh so agents can not only avoid them but also move along those objects outline at high detail");
|
||||
}
|
||||
|
||||
return String();
|
||||
@ -162,13 +169,13 @@ void NavigationObstacle::reevaluate_agent_radius() {
|
||||
}
|
||||
|
||||
real_t NavigationObstacle::estimate_agent_radius() const {
|
||||
if (parent_spatial) {
|
||||
if (parent_spatial && parent_spatial->is_inside_tree()) {
|
||||
// Estimate the radius of this physics body
|
||||
real_t radius = 0.0;
|
||||
for (int i(0); i < parent_spatial->get_child_count(); i++) {
|
||||
// For each collision shape
|
||||
CollisionShape *cs = Object::cast_to<CollisionShape>(parent_spatial->get_child(i));
|
||||
if (cs) {
|
||||
if (cs && cs->is_inside_tree()) {
|
||||
// Take the distance between the Body center to the shape center
|
||||
real_t r = cs->get_transform().origin.length();
|
||||
if (cs->get_shape().is_valid()) {
|
||||
@ -179,6 +186,9 @@ real_t NavigationObstacle::estimate_agent_radius() const {
|
||||
r *= MAX(s.x, MAX(s.y, s.z));
|
||||
// Takes the biggest radius
|
||||
radius = MAX(radius, r);
|
||||
} else if (cs && !cs->is_inside_tree()) {
|
||||
WARN_PRINT("A CollisionShape of the NavigationObstacle parent node was not inside the SceneTree when estimating the obstacle radius."
|
||||
"\nMove the NavigationObstacle to a child position below any CollisionShape node of the parent node so the CollisionShape is already inside the SceneTree.");
|
||||
}
|
||||
}
|
||||
Vector3 s = parent_spatial->get_global_transform().basis.get_scale();
|
||||
|
@ -854,8 +854,6 @@ void VoxelLightBaker::plot_light_directional(const Vector3 &p_direction, const C
|
||||
|
||||
float distance_adv = _get_normal_advance(light_axis);
|
||||
|
||||
int success_count = 0;
|
||||
|
||||
Vector3 light_energy = Vector3(p_color.r, p_color.g, p_color.b) * p_energy * p_indirect_energy;
|
||||
|
||||
int idx = first_leaf;
|
||||
@ -916,7 +914,6 @@ void VoxelLightBaker::plot_light_directional(const Vector3 &p_direction, const C
|
||||
light->direct_accum[i][2] += light_energy.z * s;
|
||||
}
|
||||
}
|
||||
success_count++;
|
||||
}
|
||||
|
||||
idx = light_data[idx].next_leaf;
|
||||
|
@ -332,7 +332,7 @@ bool SceneTreeTween::can_process(bool p_tree_paused) const {
|
||||
if (is_bound && pause_mode == TWEEN_PAUSE_BOUND) {
|
||||
Node *bound_node = get_bound_node();
|
||||
if (bound_node) {
|
||||
return bound_node->can_process();
|
||||
return bound_node->is_inside_tree() && bound_node->can_process();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,8 @@ void Button::_notification(int p_what) {
|
||||
|
||||
if (expand_icon) {
|
||||
Size2 _size = get_size() - style->get_offset() * 2;
|
||||
_size.width -= get_constant("hseparation") + icon_ofs_region;
|
||||
int icon_text_separation = text.empty() ? 0 : get_constant("h_separation");
|
||||
_size.width -= icon_text_separation + icon_ofs_region;
|
||||
if (!clip_text && icon_align != ALIGN_CENTER) {
|
||||
_size.width -= get_font("font")->get_string_size(xl_text).width;
|
||||
}
|
||||
|
@ -142,12 +142,45 @@ void GridContainer::_notification(int p_what) {
|
||||
}
|
||||
|
||||
// Finally, fit the nodes.
|
||||
int col_expand = col_expanded.size() > 0 ? remaining_space.width / col_expanded.size() : 0;
|
||||
int row_expand = row_expanded.size() > 0 ? remaining_space.height / row_expanded.size() : 0;
|
||||
int col_remaining_pixel = 0;
|
||||
int col_expand = 0;
|
||||
if (col_expanded.size() > 0) {
|
||||
col_expand = remaining_space.width / col_expanded.size();
|
||||
col_remaining_pixel = remaining_space.width - col_expanded.size() * col_expand;
|
||||
}
|
||||
|
||||
int row_remaining_pixel = 0;
|
||||
int row_expand = 0;
|
||||
if (row_expanded.size() > 0) {
|
||||
row_expand = remaining_space.height / row_expanded.size();
|
||||
row_remaining_pixel = remaining_space.height - row_expanded.size() * row_expand;
|
||||
}
|
||||
|
||||
int col_ofs = 0;
|
||||
int row_ofs = 0;
|
||||
|
||||
// Calculate the index of rows and columns that receive the remaining pixel.
|
||||
int col_remaining_pixel_index = 0;
|
||||
for (int i = 0; i < max_col; i++) {
|
||||
if (col_remaining_pixel == 0) {
|
||||
break;
|
||||
}
|
||||
if (col_expanded.has(i)) {
|
||||
col_remaining_pixel_index = i + 1;
|
||||
col_remaining_pixel--;
|
||||
}
|
||||
}
|
||||
int row_remaining_pixel_index = 0;
|
||||
for (int i = 0; i < max_row; i++) {
|
||||
if (row_remaining_pixel == 0) {
|
||||
break;
|
||||
}
|
||||
if (row_expanded.has(i)) {
|
||||
row_remaining_pixel_index = i + 1;
|
||||
row_remaining_pixel--;
|
||||
}
|
||||
}
|
||||
|
||||
valid_controls_index = 0;
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *c = Object::cast_to<Control>(get_child(i));
|
||||
@ -162,14 +195,26 @@ void GridContainer::_notification(int p_what) {
|
||||
col_ofs = 0;
|
||||
if (row > 0) {
|
||||
row_ofs += (row_expanded.has(row - 1) ? row_expand : row_minh[row - 1]) + vsep;
|
||||
|
||||
if (row_expanded.has(row - 1) && row - 1 < row_remaining_pixel_index) {
|
||||
// Apply the remaining pixel of the previous row.
|
||||
row_ofs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Point2 p(col_ofs, row_ofs);
|
||||
Size2 s(col_expanded.has(col) ? col_expand : col_minw[col], row_expanded.has(row) ? row_expand : row_minh[row]);
|
||||
|
||||
fit_child_in_rect(c, Rect2(p, s));
|
||||
// Add the remaining pixel to the expanding columns and rows, starting from left and top.
|
||||
if (col_expanded.has(col) && col < col_remaining_pixel_index) {
|
||||
s.x++;
|
||||
}
|
||||
if (row_expanded.has(row) && row < row_remaining_pixel_index) {
|
||||
s.y++;
|
||||
}
|
||||
|
||||
Point2 p(col_ofs, row_ofs);
|
||||
fit_child_in_rect(c, Rect2(p, s));
|
||||
col_ofs += s.width + hsep;
|
||||
}
|
||||
|
||||
|
@ -223,7 +223,7 @@ float NavigationMesh::get_verts_per_poly() const {
|
||||
}
|
||||
|
||||
void NavigationMesh::set_detail_sample_distance(float p_value) {
|
||||
ERR_FAIL_COND(p_value < 0);
|
||||
ERR_FAIL_COND(p_value < 0.1);
|
||||
detail_sample_distance = p_value;
|
||||
}
|
||||
|
||||
@ -494,7 +494,7 @@ void NavigationMesh::_bind_methods() {
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "edge/max_length", PROPERTY_HINT_RANGE, "0.0,50.0,0.01,or_greater"), "set_edge_max_length", "get_edge_max_length");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "edge/max_error", PROPERTY_HINT_RANGE, "0.1,3.0,0.01,or_greater"), "set_edge_max_error", "get_edge_max_error");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "polygon/verts_per_poly", PROPERTY_HINT_RANGE, "3.0,12.0,1.0,or_greater"), "set_verts_per_poly", "get_verts_per_poly");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "detail/sample_distance", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater"), "set_detail_sample_distance", "get_detail_sample_distance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "detail/sample_distance", PROPERTY_HINT_RANGE, "0.1,16.0,0.01,or_greater"), "set_detail_sample_distance", "get_detail_sample_distance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "detail/sample_max_error", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater"), "set_detail_sample_max_error", "get_detail_sample_max_error");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter/low_hanging_obstacles"), "set_filter_low_hanging_obstacles", "get_filter_low_hanging_obstacles");
|
||||
|
@ -114,6 +114,7 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
|
||||
const NodeData &n = nd[i];
|
||||
|
||||
Node *parent = nullptr;
|
||||
String old_parent_path;
|
||||
|
||||
if (i > 0) {
|
||||
ERR_FAIL_COND_V_MSG(n.parent == -1, nullptr, vformat("Invalid scene: node %s does not specify its parent node.", snames[n.name]));
|
||||
@ -121,6 +122,8 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (!nparent && (n.parent & FLAG_ID_IS_PATH)) {
|
||||
WARN_PRINT(String("Parent path '" + String(node_paths[n.parent & FLAG_MASK]) + "' for node '" + String(snames[n.name]) + "' has vanished when instancing: '" + get_path() + "'.").ascii().get_data());
|
||||
old_parent_path = String(node_paths[n.parent & FLAG_MASK]).trim_prefix("./").replace("/", "@");
|
||||
nparent = ret_nodes[0];
|
||||
}
|
||||
#endif
|
||||
parent = nparent;
|
||||
@ -305,6 +308,10 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
|
||||
}
|
||||
}
|
||||
|
||||
if (!old_parent_path.empty()) {
|
||||
node->_set_name_nocheck(old_parent_path + "@" + node->get_name());
|
||||
}
|
||||
|
||||
if (n.owner >= 0) {
|
||||
NODE_FROM_ID(owner, n.owner);
|
||||
if (owner) {
|
||||
|
@ -137,7 +137,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector
|
||||
Edge ignore_to_edge(-1, -1);
|
||||
|
||||
if (!_is_point_inside(from)) {
|
||||
float closest_dist = 1e20;
|
||||
float closest_dist = 1e20f;
|
||||
Vector2 closest_point;
|
||||
|
||||
for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) {
|
||||
@ -161,7 +161,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector
|
||||
};
|
||||
|
||||
if (!_is_point_inside(to)) {
|
||||
float closest_dist = 1e20;
|
||||
float closest_dist = 1e20f;
|
||||
Vector2 closest_point;
|
||||
|
||||
for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) {
|
||||
@ -489,7 +489,7 @@ bool PolygonPathFinder::is_point_inside(const Vector2 &p_point) const {
|
||||
}
|
||||
|
||||
Vector2 PolygonPathFinder::get_closest_point(const Vector2 &p_point) const {
|
||||
float closest_dist = 1e20;
|
||||
float closest_dist = 1e20f;
|
||||
Vector2 closest_point;
|
||||
|
||||
for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) {
|
||||
@ -508,7 +508,7 @@ Vector2 PolygonPathFinder::get_closest_point(const Vector2 &p_point) const {
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(closest_dist == 1e20, Vector2());
|
||||
ERR_FAIL_COND_V(Math::is_equal_approx(closest_dist, 1e20f), Vector2());
|
||||
|
||||
return closest_point;
|
||||
}
|
||||
|
@ -179,7 +179,15 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
}
|
||||
|
||||
list.sort();
|
||||
String prev_type;
|
||||
for (List<PropertyInfo>::Element *E = list.front(); E; E = E->next()) {
|
||||
// Add groups for types so that their names are left unchanged in the inspector.
|
||||
String current_type = E->get().name.get_slice("/", 0);
|
||||
if (prev_type != current_type) {
|
||||
p_list->push_back(PropertyInfo(Variant::NIL, current_type, PROPERTY_HINT_NONE, current_type + "/", PROPERTY_USAGE_GROUP));
|
||||
prev_type = current_type;
|
||||
}
|
||||
|
||||
p_list->push_back(E->get());
|
||||
}
|
||||
}
|
||||
|
@ -142,13 +142,18 @@ void Navigation2DServer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &Navigation2DServer::map_get_closest_point);
|
||||
ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &Navigation2DServer::map_get_closest_point_owner);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &Navigation2DServer::map_get_regions);
|
||||
ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &Navigation2DServer::map_get_agents);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("region_create"), &Navigation2DServer::region_create);
|
||||
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &Navigation2DServer::region_set_map);
|
||||
ClassDB::bind_method(D_METHOD("region_get_map", "region"), &Navigation2DServer::region_get_map);
|
||||
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &Navigation2DServer::region_set_transform);
|
||||
ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &Navigation2DServer::region_set_navpoly);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("agent_create"), &Navigation2DServer::agent_create);
|
||||
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &Navigation2DServer::agent_set_map);
|
||||
ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &Navigation2DServer::agent_get_map);
|
||||
ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &Navigation2DServer::agent_set_neighbor_dist);
|
||||
ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &Navigation2DServer::agent_set_max_neighbors);
|
||||
ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &Navigation2DServer::agent_set_time_horizon);
|
||||
@ -171,6 +176,14 @@ Navigation2DServer::~Navigation2DServer() {
|
||||
singleton = nullptr;
|
||||
}
|
||||
|
||||
Array FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid);
|
||||
|
||||
Array FORWARD_1_C(map_get_agents, RID, p_map, rid_to_rid);
|
||||
|
||||
RID FORWARD_1_C(region_get_map, RID, p_region, rid_to_rid);
|
||||
|
||||
RID FORWARD_1_C(agent_get_map, RID, p_agent, rid_to_rid);
|
||||
|
||||
RID FORWARD_0_C(map_create);
|
||||
|
||||
void FORWARD_2_C(map_set_active, RID, p_map, bool, p_active, rid_to_rid, bool_to_bool);
|
||||
|
@ -82,11 +82,15 @@ public:
|
||||
virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const;
|
||||
virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const;
|
||||
|
||||
virtual Array map_get_regions(RID p_map) const;
|
||||
virtual Array map_get_agents(RID p_map) const;
|
||||
|
||||
/// Creates a new region.
|
||||
virtual RID region_create() const;
|
||||
|
||||
/// Set the map of this region.
|
||||
virtual void region_set_map(RID p_region, RID p_map) const;
|
||||
virtual RID region_get_map(RID p_region) const;
|
||||
|
||||
/// Set the global transformation of this region.
|
||||
virtual void region_set_transform(RID p_region, Transform2D p_transform) const;
|
||||
@ -99,6 +103,7 @@ public:
|
||||
|
||||
/// Put the agent in the map.
|
||||
virtual void agent_set_map(RID p_agent, RID p_map) const;
|
||||
virtual RID agent_get_map(RID p_agent) const;
|
||||
|
||||
/// The maximum distance (center point to
|
||||
/// center point) to other agents this agent
|
||||
|
@ -54,14 +54,19 @@ void NavigationServer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer::map_get_closest_point_normal);
|
||||
ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer::map_get_closest_point_owner);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer::map_get_regions);
|
||||
ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer::map_get_agents);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer::region_create);
|
||||
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer::region_set_map);
|
||||
ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer::region_get_map);
|
||||
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer::region_set_transform);
|
||||
ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer::region_set_navmesh);
|
||||
ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer::region_bake_navmesh);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer::agent_create);
|
||||
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer::agent_set_map);
|
||||
ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer::agent_get_map);
|
||||
ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer::agent_set_neighbor_dist);
|
||||
ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer::agent_set_max_neighbors);
|
||||
ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer::agent_set_time_horizon);
|
||||
|
@ -101,11 +101,15 @@ public:
|
||||
virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const = 0;
|
||||
virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const = 0;
|
||||
|
||||
virtual Array map_get_regions(RID p_map) const = 0;
|
||||
virtual Array map_get_agents(RID p_map) const = 0;
|
||||
|
||||
/// Creates a new region.
|
||||
virtual RID region_create() const = 0;
|
||||
|
||||
/// Set the map of this region.
|
||||
virtual void region_set_map(RID p_region, RID p_map) const = 0;
|
||||
virtual RID region_get_map(RID p_region) const = 0;
|
||||
|
||||
/// Set the global transformation of this region.
|
||||
virtual void region_set_transform(RID p_region, Transform p_transform) const = 0;
|
||||
@ -121,6 +125,7 @@ public:
|
||||
|
||||
/// Put the agent in the map.
|
||||
virtual void agent_set_map(RID p_agent, RID p_map) const = 0;
|
||||
virtual RID agent_get_map(RID p_agent) const = 0;
|
||||
|
||||
/// The maximum distance (center point to
|
||||
/// center point) to other agents this agent
|
||||
|
@ -526,7 +526,6 @@ int PortalRoomsBSP::evaluate_room_split_plane(int p_room_a_id, int p_room_b_id,
|
||||
int PortalRoomsBSP::evaluate_plane(const VSPortal *p_portal, const Plane &p_plane, const LocalVector<int32_t, int32_t> &p_room_ids, LocalVector<int32_t, int32_t> *r_room_ids_back, LocalVector<int32_t, int32_t> *r_room_ids_front) {
|
||||
int rooms_front = 0;
|
||||
int rooms_back = 0;
|
||||
int rooms_split = 0;
|
||||
|
||||
if (r_room_ids_back) {
|
||||
DEV_ASSERT(!r_room_ids_back->size());
|
||||
@ -622,8 +621,6 @@ int PortalRoomsBSP::evaluate_plane(const VSPortal *p_portal, const Plane &p_plan
|
||||
if (r_room_ids_back) {
|
||||
r_room_ids_back->push_back(rid);
|
||||
}
|
||||
|
||||
rooms_split++;
|
||||
}
|
||||
|
||||
#undef GODOT_BSP_PUSH_BACK
|
||||
|
@ -3750,10 +3750,6 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co
|
||||
|
||||
float distance_adv = _get_normal_advance(light_axis);
|
||||
|
||||
int success_count = 0;
|
||||
|
||||
// uint64_t us = OS::get_singleton()->get_ticks_usec();
|
||||
|
||||
for (int i = 0; i < p_leaf_count; i++) {
|
||||
uint32_t idx = leaves[i];
|
||||
|
||||
@ -3802,18 +3798,11 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co
|
||||
light->energy[0] += int32_t(light_r * att * ((cell->albedo >> 16) & 0xFF) / 255.0);
|
||||
light->energy[1] += int32_t(light_g * att * ((cell->albedo >> 8) & 0xFF) / 255.0);
|
||||
light->energy[2] += int32_t(light_b * att * ((cell->albedo) & 0xFF) / 255.0);
|
||||
success_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0));
|
||||
// print_line("valid cells: " + itos(success_count));
|
||||
|
||||
} break;
|
||||
case VS::LIGHT_OMNI:
|
||||
case VS::LIGHT_SPOT: {
|
||||
// uint64_t us = OS::get_singleton()->get_ticks_usec();
|
||||
|
||||
Vector3 light_pos = light_cache.transform.origin;
|
||||
Vector3 spot_axis = -light_cache.transform.basis.get_axis(2).normalized();
|
||||
|
||||
@ -3911,7 +3900,6 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co
|
||||
light->energy[2] += int32_t(light_b * att * ((cell->albedo) & 0xFF) / 255.0);
|
||||
}
|
||||
}
|
||||
//print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -107,8 +107,6 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
|
||||
}
|
||||
|
||||
if (!p_viewport->hide_canvas) {
|
||||
int i = 0;
|
||||
|
||||
Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
|
||||
|
||||
Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y);
|
||||
@ -117,8 +115,6 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
|
||||
RasterizerCanvas::Light *lights_with_mask = nullptr;
|
||||
Rect2 shadow_rect;
|
||||
|
||||
int light_count = 0;
|
||||
|
||||
for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
|
||||
VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get().canvas);
|
||||
|
||||
@ -164,8 +160,6 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
|
||||
cl->mask_next_ptr = lights_with_mask;
|
||||
lights_with_mask = cl;
|
||||
}
|
||||
|
||||
light_count++;
|
||||
}
|
||||
|
||||
VSG::canvas_render->light_internal_update(cl->light_internal, cl);
|
||||
@ -235,7 +229,6 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
|
||||
}
|
||||
|
||||
VSG::canvas->render_canvas(canvas, xform, canvas_lights, lights_with_mask, clip_rect, canvas_layer_id);
|
||||
i++;
|
||||
|
||||
if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
|
||||
if (!can_draw_3d) {
|
||||
|
@ -233,9 +233,9 @@ struct btSparseSdf
|
||||
//int sz = sizeof(Cell);
|
||||
if (ncells > m_clampCells)
|
||||
{
|
||||
static int numResets = 0;
|
||||
numResets++;
|
||||
// printf("numResets=%d\n",numResets);
|
||||
//static int numResets = 0;
|
||||
//numResets++;
|
||||
//printf("numResets=%d\n",numResets);
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
17
thirdparty/bullet/patches/fix-unused-but-set-warning.patch
vendored
Normal file
17
thirdparty/bullet/patches/fix-unused-but-set-warning.patch
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
diff --git a/thirdparty/bullet/BulletSoftBody/btSparseSDF.h b/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
|
||||
index ae1288d9e6..243b80f8ae 100644
|
||||
--- a/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
|
||||
+++ b/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
|
||||
@@ -233,9 +233,9 @@ struct btSparseSdf
|
||||
//int sz = sizeof(Cell);
|
||||
if (ncells > m_clampCells)
|
||||
{
|
||||
- static int numResets = 0;
|
||||
- numResets++;
|
||||
- // printf("numResets=%d\n",numResets);
|
||||
+ //static int numResets = 0;
|
||||
+ //numResets++;
|
||||
+ //printf("numResets=%d\n",numResets);
|
||||
Reset();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user